J2i.Net

Nothing at all and Everything in general.

Hello World on the PlayStation® Vita

Over the past couple of weeks I decided to take a look at Sony's public SDK for developing on the PlayStation® Vita. Getting to the point of being able to do a deployment was a bit painful, but after getting through those initial obstacles it's easy from there. A few things worth noting is that the SDK uses C# is the main programming language for making programs. It's running a custom version of Mono. Windows 8 isn't supported at this time, which causes some issues with getting the drivers installed that you will need for deployment. I've done a write up on what I had to do and have posted it over at CodeProject.com. You can find a detail account of what I had to do there. 

http://www.codeproject.com/Articles/535325/Hello-World-on-the-PlayStation-Vita-Deploying-code

Using XInput to access an Xbox 360 Controller in Managed Code

download code

Introduction

A few years ago I wrote on using XNA to access the Xbox 360 controller from a Windows Form application. I had received a question about accessing the controller in an environment in which the XNA assemblies wouldn't be appropriate. So I wrote this code as an example of accessing the controller without the XNA assemblies. This is still a managed program. But it makes use of P/Invoke to use the functionality provided in the DirectX library.

Prerequisites

I wrote this code using Visual Studio 2012. It makes use of the XInput dll which is already part of Windows. So no additional installations are needed to use the code.

What is XInput

DirectX is composed of many libraries. There's Direct3D for for rendering 3D graphics, DirectSound for playing sound, and so on. DirectInput contains functionality for accessing various input devices (joysticks, keyboards, and more). But the Xbox 360 controller is not accessed through that library. It is accessed through a different library named XInput. This library is dedicated to the the Xbox 360 controller. Let's take a look at what is in the C language header file to see what functionality it provides. On my computer I can find the header in C:\Program Files (x86)\Windows Kits\8.0\Include\um\Xinput.h.

The header starts with defining the name of the DLL in which we will find the functionality.

#if(_WIN32_WINNT >= _WIN32_WINNT_WIN8)
#define XINPUT_DLL_A  "xinput1_4.dll"
#define XINPUT_DLL_W L"xinput1_4.dll"
#else 
#define XINPUT_DLL_A  "xinput9_1_0.dll"
#define XINPUT_DLL_W L"xinput9_1_0.dll"
#endif

When a program is being compiled for an OS version before Windows 8 the functionality in the xinput1_4.dll. For programs compiled for Widnows 8 the functionality from xinput9_1_0.dll will be used. If you wanted to target both platforms you could make use of the older DLL (xinput9_1_0.dll). It will work on Windows 8 too. But the newer DLL (xinput1_4.dll) contains functionality for accessing the battery .

//
// Structures used by XInput APIs
//
typedef struct _XINPUT_GAMEPAD
{
    WORD                                wButtons;
    BYTE                                bLeftTrigger;
    BYTE                                bRightTrigger;
    SHORT                               sThumbLX;
    SHORT                               sThumbLY;
    SHORT                               sThumbRX;
    SHORT                               sThumbRY;
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;

typedef struct _XINPUT_STATE
{
    DWORD                               dwPacketNumber;
    XINPUT_GAMEPAD                      Gamepad;
} XINPUT_STATE, *PXINPUT_STATE;

typedef struct _XINPUT_VIBRATION
{
    WORD                                wLeftMotorSpeed;
    WORD                                wRightMotorSpeed;
} XINPUT_VIBRATION, *PXINPUT_VIBRATION;

typedef struct _XINPUT_CAPABILITIES
{
    BYTE                                Type;
    BYTE                                SubType;
    WORD                                Flags;
    XINPUT_GAMEPAD                      Gamepad;
    XINPUT_VIBRATION                    Vibration;
} XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES;

There's also a section that contains the newer structures for functionality that became available with Windows 8.

#if(_WIN32_WINNT >= _WIN32_WINNT_WIN8)

typedef struct _XINPUT_BATTERY_INFORMATION
{
    BYTE BatteryType;
    BYTE BatteryLevel;
} XINPUT_BATTERY_INFORMATION, *PXINPUT_BATTERY_INFORMATION;

typedef struct _XINPUT_KEYSTROKE
{
    WORD    VirtualKey;
    WCHAR   Unicode;
    WORD    Flags;
    BYTE    UserIndex;
    BYTE    HidCode;
} XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE;

#endif //(_WIN32_WINNT >= _WIN32_WINNT_WIN8)
    

Let's take a look at the structures redefined for .Net and C#.

struct XInputGamePad

The gamepad has two types of data to expose; information from the analog inputs and that from the digital inputs. The digital inputs include the A,B,X,Y, LB, and RB buttons.  It also includes the Start, Back, the four directions on the D-pad, and the buttonsunder the thumb sticks. The analog inputs include the two triggers and the two thumb sticks.  For the analog inputs there is a field for each input. The left and right triggers both an integer value between 0 and 255 in a byte. The thumb sticks return their X and Y values as 16-bit integers between the range of -32,768 and 32,767. The digital inputs are all returned in a single dield named wButtons.

[StructLayout(LayoutKind.Explicit)]
public struct  XInputGamepad
{
    [MarshalAs(UnmanagedType.I2)]
    [FieldOffset(0)]
    public short wButtons;

    [MarshalAs(UnmanagedType.I1)]
    [FieldOffset(2)]
    public byte bLeftTrigger;

    [MarshalAs(UnmanagedType.I1)]
    [FieldOffset(3)]
    public byte bRightTrigger;

    [MarshalAs(UnmanagedType.I2)]
    [FieldOffset(4)]
    public short sThumbLX;

    [MarshalAs(UnmanagedType.I2)]
    [FieldOffset(6)]
    public short sThumbLY;

    [MarshalAs(UnmanagedType.I2)]
    [FieldOffset(8)]
    public short sThumbRX;

    [MarshalAs(UnmanagedType.I2)]
    [FieldOffset(10)]
    public short sThumbRY;


    public bool IsButtonPressed(int buttonFlags)
    {
        return (wButtons & buttonFlags) == buttonFlags;
    }

    public bool IsButtonPresent(int buttonFlags)
    {
        return (wButtons & buttonFlags) == buttonFlags;
    }



    public void Copy(XInputGamepad source)
    {
        sThumbLX = source.sThumbLX;
        sThumbLY = source.sThumbLY;
        sThumbRX = source.sThumbRX;
        sThumbRY = source.sThumbRY;
        bLeftTrigger = source.bLeftTrigger;
        bRightTrigger = source.bRightTrigger;
        wButtons = source.wButtons;
    }

    public override bool Equals(object obj)
    {
        if (!(obj is XInputGamepad))
            return false;
        XInputGamepad source = (XInputGamepad)obj;
        return ((sThumbLX == source.sThumbLX) 
        && (sThumbLY == source.sThumbLY)
        && (sThumbRX == source.sThumbRX)
        && (sThumbRY == source.sThumbRY)
        && (bLeftTrigger == source.bLeftTrigger)
        && (bRightTrigger == source.bRightTrigger)
        && (wButtons == source.wButtons)); 
    }
}

The method IsButtonPressed accepts a constant that identifies the button of interest and will look in the wButtons member to see if the button is pressed and return true or false accordingly. I've added a few methods to make the the structure easier to use. The methods IsButtonPressed and IsButtonPresent have the exact same implementation. The same structure is used for querying the state of the controller and the capabilities of the controller.  I've added the two methods as a notational difference.

XInputVibration

The XInputVibration structure contains two unsigned integers between 0 and 65,535. The higher the value placed in the structure the faster the associated motor will be when it is turned on.

    [StructLayout(LayoutKind.Sequential)]
public struct  XInputVibration
{
    [MarshalAs(UnmanagedType.I2)]
    public ushort LeftMotorSpeed;

    [MarshalAs(UnmanagedType.I2)]
    public ushort RightMotorSpeed;
}

XInputState

The XInputState structure is an extension of the XInputGamepad structure with an additional field, PacketNumber. When the state of the controller is queried several times this value will continue to be the same if the the state of the controller is the same from the last time it was queried. If the state of the controller has changed then this value will be different.

[StructLayout(LayoutKind.Explicit)]
public struct  XInputState
{
        [FieldOffset(0)]
    public int PacketNumber;

        [FieldOffset(4)]
    public XInputGamepad Gamepad;

        public void Copy(XInputState source)
        {
            PacketNumber = source.PacketNumber;
            Gamepad.Copy(source.Gamepad);
        }

        public override bool Equals(object obj)
        {
            if ((obj == null) || (!(obj is XInputState)))
                return false;
            XInputState source = (XInputState)obj;

            return ((PacketNumber == source.PacketNumber)
                && (Gamepad.Equals(source.Gamepad)));
        }
}

XInputCapabilities

The XInputCapabilities structure returns the capabilities of the controller. Not all Xbox controlls have all of the available buttons on them, such as the dance pads which generally only contains.  Ironically the the Type field will always be populated with the same value (this may change in the future) and can be ignored for now. The field of interest is the SubType field. You can tell whether the controller is a gamepad, arcade stick, steeringwheel, or other type of controller. You can see a list of the controller types in the subtypes documentation page.  I've added the enumeration ControllerSubtypes to the XInputConstants.cs file which contains the possible values for this field. Other capabilities of the controller are indicated in the Flags member. This includes whether or not the controller is wireless, supports voice, has navigation buttons (start, back, dpad), supports force feedback, and whether it has a plugin module like the chat pad.  The possible values can be viewed in the enumeration CapabilityFlags in XInputConstants.cs.

The The next field is a XinputGamepad. For each one of the possible inputs there will be a non-zero value if the controller supports that input. After the XInputGamepad structure is a XInputVibration structure. Like the XInputGamepad if the left and right motors are supported there will be a non-zero value in the fields of this structure.

[StructLayout(LayoutKind.Explicit)]
public struct  XInputCapabilities
{
    [MarshalAs(UnmanagedType.I1)]
    [FieldOffset(0)]
    byte Type;

    [MarshalAs(UnmanagedType.I1)]
    [FieldOffset(1)]
    public byte SubType;

    [MarshalAs(UnmanagedType.I2)]
    [FieldOffset(2)]
    public short Flags;

        
    [FieldOffset(4)]
    public XInputGamepad Gamepad;

    [FieldOffset(16)]
    public XInputVibration Vibration;
}

XInputBatteryInformation

For controllers that use batteries this structure will indicate what type of battery that the control is using and indicated the battery level. The supported battery types are NiMH, alkaline, unknown, disconnected, and wired (for devices that don't actually use batteries). For the battery level only 4 values are supported to indicated empty, low, medium, and full. The values for both of these fields are also defined in the enumerations BatteryType and BatteryLevel in the XInputConstants.cs file.

[StructLayout(LayoutKind.Explicit)]
public struct  XInputBatteryInformation
{
    [MarshalAs(UnmanagedType.I1)]
    [FieldOffset(0)]
    public byte BatteryType;

    [MarshalAs(UnmanagedType.I1)]
    [FieldOffset(1)]
    public byte BatteryLevel;
}

XInput Functions

There are four functions that I use from the XInput library for interacting with the controller, XInputGetState, XInputSetState, XInputGetCapabilities and XInputGetBatteryInformation. All of these functions take as their parameters the index of the controller that is being manipulated and a reference to the structure into which information will be stored or retrieved. The two functions XInputGetBatteryInformation and XInputGetCapabilities take an additional parameter. For XInputGetBatteryInformation takes a parameter to the device type to be probed. If a user is using a wireless headset it could have it's own battery level separate from the level of the controller. The enumeration BatteryDeviceType contains values for BATTERY_DEVTYPE_GAMEPAD and BATTERY_DEVTYPE_HEADSET for this purpose. XInputGetCapabilities only accepts a single value of INPUT_FLAG_GAMEPAD for its additional value. This parameter could accept different values in the future as more capabilities are exposed.

        [DllImport("xinput1_4.dll")]
        public static extern int XInputGetState
        (
            int dwUserIndex,  // [in] Index of the gamer associated with the device
            ref XInputState pState        // [out] Receives the current state
        );

        [DllImport("xinput1_4.dll")]
        public static extern int XInputSetState
        (
            int dwUserIndex,  // [in] Index of the gamer associated with the device
            ref XInputVibration pVibration    // [in, out] The vibration information to send to the controller
        );

        [DllImport("xinput1_4.dll")]
        public static extern int XInputGetCapabilities
        (
            int dwUserIndex,   // [in] Index of the gamer associated with the device
            int dwFlags,       // [in] Input flags that identify the device type
            ref XInputCapabilities pCapabilities  // [out] Receives the capabilities
        );


        [DllImport("xinput1_4.dll")]
        public static extern int XInputGetBatteryInformation
        (
              int dwUserIndex,        // Index of the gamer associated with the device
              byte devType,            // Which device on this user index
            ref XInputBatteryInformation pBatteryInformation // Contains the level and types of batteries
        );

XboxController Class

Now that I've talked about all of the structures and functions available in XInput the one other class to present is one that I've made to manage the use of these other classes. I've wrapped the calls to the functionality in a class named XboxController class. The constructor for this class is private. There can only be up to 4 Xbox controllers on a system. So I've restricted the access to the constructor to prevent more than 4 instances from being created. To get an instance of a controller the static method XbocController.RetrieveController is available.

It's necessary to poll the controller to continually get updates about it's state. In an XNA or DirectX program this would be part of your game loop and so you don't really need to think about it. If you use the class in an environment without such a loop there are two options for getting updates to the controller. You could either call UpdateState manually or you could call the static method XboxController.StartPolling. The static method will create a new thread that will update the controller's state on some frequency. By default I've set this to 25 times per second. If you want to change it to some other value assign the number of updates per second that you want to received to the static member UpdateFrequency. When you nolonger wish to receive updates remember to call the XboxController.StopPolling method to end the thread. In the example code that I've attached to this article I call the StopPolling method when the program is closed.

protected override void OnClosing(CancelEventArgs e)
{
    XboxController.StopPolling();
    base.OnClosing(e);
}

There's a single event exposed by the class named StateChanged that is called if something about the controller's state has changed from the last thethat it was called.The e vent arguments for this event contain the current and previous state of the controller.

For making the controller vibrate call the Vibrate method. You could call this method by passing two double values (between 0.0d and 1.0d) to indicate how fast the motor should be. Values higher than 1.0 are clamped down to 1.0. Optionally you can specify the amount of time that the motor should be on. If no timespan is specific the motor will remain on until there's another call to Vibrate specifying a speed of zero. The polling loop for the Xbox controller class also checks to see if it is time to turn off any motors (if a timespan had been specified.

#region Motor Functions
public void Vibrate(double leftMotor, double rightMotor)
{
    Vibrate(leftMotor, rightMotor, TimeSpan.MinValue);
}

public void Vibrate(double leftMotor, double rightMotor, TimeSpan length)
{
    leftMotor = Math.Max(0d, Math.Min(1d, leftMotor));
    rightMotor = Math.Max(0d, Math.Min(1d, rightMotor));

    XInputVibration vibration = new XInputVibration() { LeftMotorSpeed = (ushort)(65535d * leftMotor), RightMotorSpeed = (ushort)(65535d * rightMotor) };
    Vibrate(vibration, length);
}
        

public void Vibrate(XInputVibration strength)
{
    _stopMotorTimerActive = false;
    XInput.XInputSetState(_playerIndex, ref strength);
}

public void Vibrate(XInputVibration strength, TimeSpan length)
{
    XInput.XInputSetState(_playerIndex, ref strength);
    if (length != TimeSpan.MinValue)
    {
        _stopMotorTime = DateTime.Now.Add(length);
        _stopMotorTimerActive = true;
    }
}
#endregion

Most importantly the XBoxController has a property input so that you can read its state. For the digital inputs reading one of the methods indirectly results in a call to IsButtonPressed.

#region Digital Button States
public bool IsDPadUpPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_DPAD_UP); }
}

public bool IsDPadDownPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_DPAD_DOWN); }
}

public bool IsDPadLeftPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_DPAD_LEFT); }
}

public bool IsDPadRightPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_DPAD_RIGHT); }
}

public bool IsAPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_A); }
}

public bool IsBPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_B); }
}

public bool IsXPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_X); }
}

public bool IsYPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_Y); }
}


public bool IsBackPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_BACK); }
}


public bool IsStartPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_START); }
}


public bool IsLeftShoulderPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_LEFT_SHOULDER); }
}


public bool IsRightShoulderPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_RIGHT_SHOULDER); }
}

public bool IsLeftStickPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_LEFT_THUMB); }
}

public bool IsRightStickPressed
{
    get { return gamepadStateCurrent.Gamepad.IsButtonPressed((int)ButtonFlags.XINPUT_GAMEPAD_RIGHT_THUMB); }
}
#endregion

For the analog inputs a numeric value is returned for the left or right triggers, or a pair of numeric values (for X and Y directions) are returned for the thumbsticks.

#region Analogue Input States
public int LeftTrigger
{
    get { return (int)gamepadStateCurrent.Gamepad.bLeftTrigger;  }
}

public int RightTrigger
{
    get  {  return (int)gamepadStateCurrent.Gamepad.bRightTrigger; }
}

public Point LeftThumbStick
{
    get
    {
        Point p = new Point()
        {
            X = gamepadStateCurrent.Gamepad.sThumbLX,
            Y = gamepadStateCurrent.Gamepad.sThumbLY
        };
        return p;
    }
}

public Point RightThumbStick
{
    get
    {
        Point p = new Point()
        {
            X = gamepadStateCurrent.Gamepad.sThumbRX,
            Y = gamepadStateCurrent.Gamepad.sThumbRY
        };
        return p;
    }
}

#endregion

Setting the Display for a WPF Application

I'm working on a presenttion project for which I needed to set the display on which a set of WPF applications are running. There's a total of 6 WPF applications that will be running on the same machine at once. Each application is going to be running on a different display. I thought I would share the solution that I used to control which display that each instance of this application went to. 

The first thing I needed to do was to retrieve the information on how how many displays that the computer has and the coordinates of each display. The computer creates a single (logical) display and maps each display device to cover a range of coordinates on this logical display. So I needed to retrieve a list of the displays and the coordinates to which it is mapped. The class available for doing this is in in the System.Windows.Forms library. Since I wasn't making a Windows Forms application I didn't want to add a using directive that would include the entire library; if I did there would be some class names that exists both in this name space and a WPF name space that I was using that could cause some resolution issues. So I only included the single class from the namespace. 

using Screen=System.Windows.Forms.Screen

The Screen class contains a member named <code>AllScreens</code> that contains a collection of <code>Screen</code> objects that give the information on each screen. If you wanted to make a simple WPF program that displayed all of the screens and their positions it only takes a few lines of code. The following is the code for the code-behind and the XAML for such a program. 

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = Screen.AllScreens;
    }
}
<Window x:Class="ScreenTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox ItemsSource="{Binding}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Vertical">
                        
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="100" />
                            </Grid.ColumnDefinitions>
                            <TextBlock Text="{Binding DeviceName}" />
                            <TextBlock Grid.Column="1" Text="{Binding WorkingArea.X}" />
                            <TextBlock Grid.Column="2" Text="{Binding WorkingArea.Y}" />
                            <TextBlock Grid.Column="3" Text="{Binding WorkingArea.Width}" />
                            <TextBlock Grid.Column="4" Text="{Binding WorkingArea.Height}" />
                        </Grid>
                    </StackPanel>
                    
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>
 

Screenshot of the interface running

 

For the programs that I'll be running I've set device name for the program's intended display in a configuration file. The typical display name for the first display is \\.\DISPLAY1. I've made a method that will take the indended display name, try to find it, and set the position and size of the window accordingly.

void SetTargetDisplay()
{
    var targetDeviceName = Settings.Default.DisplayDevice;
    if(!String.IsNullOrEmpty(targetDeviceName))
    {
        // see if the device name specified exists here. It's possible
        // this was configured  to  run on a different machine and the 
        // configured device might not exists
        var screen = (from s in Screen.AllScreens 
             where s.DeviceName.ToLower().Equals(targetDeviceName.ToLower()) 
             select s).FirstOrDefault();
        if (screen != null)
        {
            Left = screen.WorkingArea.Left;
            Top = screen.WorkingArea.Top;
            Width = screen.WorkingArea.Width;
            Height = screen.WorkingArea.Height;
        }
    }
}

If the display doesn't exists (which could happen because of a typographical error or the program having been configured for another machine) then the method will just ignore the request.

 

Sidereal Time Calculator

Download Code (1.15 MB)
   

Introduction

There are a number of applications available on various mobile devices that allow you to aim your device at the sky and identify various heavenly bodies. I find the ability of identifying a body based on a user's location and the device's orientation fascinating. I find it even more fascinating when I see physical hardware acting on this information; the telescope I have uses GPS (to get my location and the current time) and uses this information to automatically move the telescope to the orientation needed to see selected body.

I now have a pretty good understanding of how it works. A significant amount of the calculations involved are based on time and another part is based on coordinate conversion. With the right time conversions you'll have enough information to get the orientation of the stars. (Getting the orientation of the planets and moon requires a little more work, but the stars have no apparent motion with respect to the solar system). I only want to talk about time for now, as there's more than enough information on time to fill an article.

Table of Contents

Terms and Time Units

Time is usually described in terms of some cyclic process or event where the units of time are from counting the cycles/events. This could be from the vibration of a crystal, the passing of some celestial, or some other event. Historically the apparent motion of the sun and moon have been used as the periodic event around which our time system was based. We've all used the units of time that are derived from these events; hours, minutes, seconds, years, and months along with the terms AM, PM, AD, and BC, and degrees. Let's dissect the physical events behind these terms.

Roman Calendar

The Roman calendar is said to have been invented by Romulus (the founder of Rome) around 753 years BC. This calendar had 10 months with the vernal equinox being the first month. The calendar had 304 days plus an additional number of winter days that stretched from December to the following month that were not part of any month on the calendar.

Julian Calendar

The Julian calendar is a modified version of the Roman Calendar. It has 365 days divided into 12 months. Once every 4 years a leap day is added.  It sounds very much like the civil calendar that we use today with the exception we don't have leap days on years divisible by 400 but not a millennium. With enough time solar and seasons events would begin to creep to other parts of the calendar. This was corrected with the Gregorian calendar.

Gregorian Calendar, Astronomical Year, and Julian Dates

The Gregorian calendar (also called the Western Calendar or Civil Calendar) is the name of the calendar that most of the world knows, loves, and uses today. The namesake for the calendar is Pope Gregory XIII. The number of times the earth rotates during its orbit around the sun is 365 times plus some fractional units (approximately 0.2524).   The Julian calendar made an attempt to correct this by introducing a leap year every 4 years. This contribution slowed the rate at which the seasons migrated on the calendar but didn't stop it all together. Pope Gregory XIII's contribution to the calendar was to not have a leap year if the year was divisible by 400 and is a  millennial year. The last day of the Julian calendar was Thursday 4 October 1582. The day that came after this was the first day of the Gregorian calendar; Friday 15 October 1582. The date range of 5-14 October (inclusive) doesn't exist - something that needs to be remembered for time conversions that cross this boundary.

Julian Date

Another commonly used calendar is counting the number of days since noon of 1 January 4713 B.C. This is also called a Julian date. Noon of 1 January 4713 is Julian date 0. Midnight between 1 January 4713 and 2 January 4714 is Julian date 0.5. Note that the time of day is a part of the Julian date as a fractional unit. For more recent dates the number used to express the Julian date is over 2,400,000 million. To avoid dealing with unnecessarily large numbers there's also the Modified Julian Date (MJD) which counts the number of days since midnight 17 November 1858. Note that MJD starts at midnight while JD starts at noon. So the time units in these two date expressions will have a difference of 0.5 for the digits after the decimal point. You may also hear of a Julian Date Number, which is just the integer portion of the Julian Date.  Dates of this form are of special significance to astronomical calculations.

AD, BC, and Astronomical Year

One of the oddities about the system of tracking years is that there is no year zero. The first year of the calendar , based on the reckoned conception of Jesus Christ of the Christian religion, is 1 AD (AD = Anno Domino, Latin for "Year of the lord", also written as "CE" for Common Era). The year immediately proceeding this is 1 BC (BC = Before Christ. Sometimes written as BCE for Before Common Era). When doing astronomical calculations no one wants to deal with the lack of the zero. So there is also the concept of the Astronomical Year. Astronomical years for the most part align with our current system of tracking years. So 1984 AD is also the Astronomical Year 1984. The difference is apparent when you look at years in the BC range. 1 BC is the astronomical year 0. 2 BC is the astronomical year -1, and so on.

Solar Day

A solar day is the period over which the sun apparently moves on a path and returns to it's starting point. I say apparent because while we know this phenomenon is from the earths rotation. But the movement of the sun is still described in geocentric terms (sun rise, sun set, so on). The sun's path varies slightly from one day to another so it doesn't really return to it's starting point. So the meridian is used as the starting line. The meridian is the imaginary circle around the globe stretching from the north pole to the south pole. The  sun and other bodies reach their highest point in the sky at the meridian and then go from climbing to declining. This line is also used to divide a day in half. Once the sun goes past the meridian the time is labeled as post meridian (P.M.). When it passes this line on the opposite side of the globe we say that it is in it's before meridian. The Latin word for before is "ante", so it is referred to as A.M. (for Ante Meridian). When the sun is on the meridian it is at its highest point in the sky. This is called "solar noon." Solar noon doesn't necessarily occur at the same instance in which the local time is 12:00 PM. There are slight variations in the time at which the sun reaches this point that we tend to ignore with civil clocks.

The pathway that the sun travels around an observer us usually divided into 24 units . Note that if you divide the 360 degrees of a circle by 24 you get 15. These 24 equal units are called hours (in other words, one hour of rotation is 15 degrees). These 15 degrees may also be divided into 60 units (minutes). A minute of rotation is 15/60, or 0.25 of a degree. As you may have guessed the next level of division is to divide a minute into 60 equal parts (the second) which contains 0.26/60 of a degree. An inference that you can make from using hours, minutes, and seconds (HMS) are a rotational unit is that for every hour that passes you can approximate the rotational distance that a celestial body in the night sky will travel over a unit of time; in a 2 hour period an object will travel 60 degrees. I say approximate because if you measure the distance with a high precision you'll see that the sun and moon appear to move by a slightly different amount than 60 degrees over this time period. For casual observations this difference won't be noticeable.

Sidereal Day

If you use the sun as your reference for rotation distance it appears that the earth takes 24 hours to make one full rotation. This isn't quite correct though. The earth moves about 1 degree on its orbit around the sun each day. So the sun shouldn't be used for an accurate measurement of how far the earth has rotated. Any other star will do though. The other stars are far enough away such that their apparent position is the same regardless of where the earth is on its orbit.

Difference in sidereal and solar day.

Choose a star (other than our sun, any star will do). Every time the earth rotates that star will reach the meridian. if you used a wall clock to measure the amount of time it takes for a star to reach the meridian again you'll find it isn't quite 24 hours. It is 23 hours 56 minutes and 4 seconds. Days measured using this method are sidereal days. Because these days are a bit less than 24 hours the amount of solar days in a sidereal year is about 366.25 instead of 365.25. Since a sidereal day is shorter than a solar day on any given solar day there will exist a range of sidereal times that occur twice within the solar day.

Time zones

Our universal time system is based on the time at Greenwich. Greenwich is on the zero longitude. Observations of celestial events on it's meridian was once the foundation of our timing system. It's meridian is also called the prime meridian. As a matter of convenience we also have the concept of local time, which is derived by adding some number of minutes and hours to the time at Greenwich. The earth is divided into 40 regions that share local time. These areas, or time zones, usually have a time difference by some interval of hours from the time at Greenwich (GMT). there are some time zones that are also offset by some hour interval plus 30 minutes. The difference from the most positive offset to the most negative offset is 26 hours. On average the difference between time zones can be inferred by their longitude (recall that one hour is 15 degrees of rotation). However the time zone lines are not straight. Rather than divide small geographic areas into several time zones the time zone borders will coincide with the borders of that geographical region.

The Earth's Celestia Movements

The stars are perceivably in a fixed position. For some one that wants to be extremely technical the stars are moving at speeds that we would find to be incredibly fast relative to our position or relative to the galaxy in which they rotate. But they are so far away that their movement is imperceptible to us, allowing us to treat them as stationary bodies over short periods measured in hundreds of years. There are a few factors that impact the orientation of the stars with respect to an observer on the earth.

Of these movements the one that has the most immediate impact on an observer is the rotation of the earth. Its impacts are directly observable through the apparent path that the sun, moon, and other bodies travel through our sky. If you are looking at a body with a telescope the movement becomes more apparent unless you have a motorized telescope that automatically adjust; as you look at a body it will drift out of the view of your telescope within a minute or less. This is the movement with which I am most concerned.

The Earth advances about 1 degree per day as it travels around the sun. With each day that passes the part of the celestial sphere that becomes unobservable due to competing light with the sun will slightly shift. This will mean that some stars will not be visible during certain parts of the year. While their direction can still be determined with the exception of an eclipse you won't be able to observer these stars during the day. Also note that this impacts the time of sun rise, sun set, and the number of hours in a day in which sunlight is visible (there's less hours of daylight in the winter). For now I'm not particularly concerned with what hours a star will be visible during my general case scenarios. Since I only use my telescope when time and weather unexpectedly permit I don't do much fore planning. If you've got interest in this I would suggest first explore the definitions on the various definitions of twilight (ex: civil vs. nautical vs. astronomical).

The third movement occurs over the course of about 25,700 years. It causes a slight circular drift of the direction in which the earth's rotational axis is pointing.  It can be addressed through a time dependent coordinate space adjustment. But I don't want to talk about coordinate conversions in this post. Just in case you are curious, the Earth's shift of the direction of it's rotational axis is about 1 degree every 71 years, so we can ignore this movement for now and it won't have a significant impact on our results.

Local Sidereal Time

Because of the continually varying orientation of the earth with respect to the sun we don't want to use a solar day for calculations of where stars are located with respect to the earth. The sidereal time is what we want. To get the sidereal time we need to know the Julian date. We'll get the Julian date from the civil (Gregorian) date. I've made a set of extensions for getting these dates. In calculating the Gregorian date you will need to be able to calculate how far we are into a day in decimal format. 12:00 Noon would be 0.5 into a day, 18:00 is 0.75 into a day, and so on. These can be easily calculated from a date or a time.

 static double ToFractionalDay(this TimeSpan sourceTime)
{
    return sourceTime.TotalHours / 24d;
}

 static double ToFractionalDay(this DateTime sourceDate)
 {
     return sourceDate.TimeOfDay.ToFractionalDay();
 }

These are written as extension methods because I find the calling syntax to be cleaner.  Now that we know how far we are into a day we can use that information to calculate the Julian date.

public static double ToJulianDate(this DateTime  sourceDate)
{
    double y, m, c;
    if (sourceDate.Month <= 2)
    {
        y = sourceDate.Year - 1;
        m = sourceDate.Month + 2;
    }
    else
    {
        y = sourceDate.Year;
        m = sourceDate.Month;
    }

    double leapDayCount  = (sourceDate > GregorianReformDate) ? (2 - Math.Floor(y / 100) + Math.Floor(y/400) ) : 0;
    if (sourceDate.Year < 0)
        c = (int)(365.25 * (double)sourceDate.Year - 0.75);
    else
        c = (int)(365.25 * (double)sourceDate.Year);
    double d = Math.Floor(30.6001 * (m + 1));
    var retVal = leapDayCount +c+ d + sourceDate.Day + 1720994.5;
    return retVal + sourceDate.ToFractionalDay();;
}

There's something I've not mentioned. All of these calculations are centric to the 0 longitude and are based on the GMT time zone without daylight savings. If you want to adjust the results to figure out the orientation of your time zone with respect to the rest of the observable universe you'll need to make an adjustment for your longitude. If your longitude is to the west of GMT express it with a negative number, otherwise use a positive number. Divide this number by 15 and add it to the sidereal time.  I live 84 degrees west of the 0 longitude. So to get the local sidereal time I do the following.

localSiderealTimeClock.CurrentTime = DateTime.Now.ToUniversalTime().ToSiderealTime().Add(TimeSpan.FromHours(-84d/15d));

The local sidereal time describes your rotational displacement from the direction of the vernal equinox (♈). While there's no up in space the direction formed by drawing a line from the sun to the earth while it is in the vernal equinox is the foundation of a couple of celestial coordinate systems (Ecliptic, which is based on the earth's orbit around the sun and equitorial which is based on the earth's rotation).

Correcting Variance's in the User's Clock

User's both intentionally and unintentionally may have their clocks set to an incorrect time. One way of avoiding problems from this is to make use of NTP (Network Time Protocol). I've written on obtaining NTP time before. You can read about it here.  While it is possible to continually poll an NTP source for the time I only grab it once every few minutes. When I get the NTP time the difference between the user's close and the NTP time source is saved and added to the value that comes from the user's clock. The expectation is that between refreshes for the NTP time the user's clock will reliably count seconds without any significant drift (if it doesn't, then the user needs a new device!).

NtpClient _ntpClient;
TimeSpan _ntpOffset;
DateTime _lastNtpRefresh = DateTime.MinValue;
TimeSpan _ntpRefreshPeriod = TimeSpan.FromMinutes(1);

public MainViewModel()
{
    _ntpClient = new NtpClient();
    _ntpClient.TimeReceived += new EventHandler<NtpClient.TimeReceivedEventArgs>(_ntpClient_TimeReceived);
    //Default the difference to zero and provisionally assume the user's
    //clock is correct until we receive information of otherwise
    _ntpOffset = TimeSpan.Zero;
}

void _ntpClient_TimeReceived(object sender, NtpClient.TimeReceivedEventArgs e)
{
    _lastNtpRefresh = DateTime.Now;
    DateTime NtpTime = e.CurrentTime;
    // NTP time is always in universal time, so we need to adjust the system clock 
    // to universal before getting the time offset. 
    _ntpOffset = NtpTime.Subtract(DateTime.Now.ToUniversalTime());
}

//Use thie method to get time adjusted for NTP offset.
DateTime GetDate()
{  
     return DateTime.Now.Add(_ntpOffset);
}

Displaying the Time

If you've looked at clocks that show the time in more than one time zone chances are the numbers shown for minutes and seconds were the same for most of the time zones. This isn't the case when looking at both civil time and sidereal time. The seconds will be out of sync. Because of personal preference (I simply find this displeasing) I'm updating the seconds simultaneously. I've made two controls for displaying the time; an analog clock and a digital clock. Both can display the time in 12 hour or 24 hour format.

 

Digital display of sidereal clock.

Displaying the 24 hour time with an analog clock may be new to many. I took a look at several 24-hour analog clocks in images online. Some started with midnight at the top of the clock and others with midnight at the bottom. I decided on having the midnight (0) hour at the bottom. This places noon at the top of the clock. Displaying 24-hour time in sidereal format is something that I'm still playing with though. While I have a circular gauge-like clock in place I'm going to change this from a user control to a templated control and expose new options on how it's to be rendered. (hints of the forthcoming changes are visible in the source code).

 
Display of analog class
 
Options screen

Help Files

In experimenting with something else I've included a Help HTML file for the application. The help file is stored in the application as content but unpackaged the first time the application is run. To prevent the unnecessary unpacking of files every time the application run it checks to see if a file already exists before unpacking it.

public class ContentUnpacker
{
   
    static string[] ContentFileList = { "About.html", "Sidereal.png", "appTimes.png", "settings.png" }; 
    public static void UnpackAllFiles()
    {
        IsolatedStorageFile sourceArchive = IsolatedStorageFile.GetUserStoreForApplication();
        if (!sourceArchive.DirectoryExists("Content"))
            sourceArchive.CreateDirectory("Content");


        foreach (string s in ContentFileList)
        {
            string targetName = String.Format("Content/{0}", s);
            string sourceName = String.Format("Content/{0}", s);
            if(!sourceArchive.FileExists(targetName))
            {
                var outStream = sourceArchive.CreateFile(targetName);
                var contentStream = Application.GetResourceStream(new Uri(sourceName, UriKind.Relative));
                using (var br = new BinaryReader(contentStream.Stream))
                {
                    var length = (int)br.BaseStream.Length;
                    outStream.Write(br.ReadBytes(length), 0, length);
                }
            }   
        }
    }
}

The about page contains only a web browser element that is given the URL to the help files. The entirity of the code that's behind the about page is below.

public partial class AboutPage : PhoneApplicationPage
{
    public AboutPage()
    {
        InitializeComponent();
    }

    private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
    {
        aboutBrowser.Navigate(new Uri("Content/About.html", UriKind.Relative));
    }
}

Where to from Here

There's a number of applications, some related to astronomy and others not that I have in mind for which this functionality will be useful. One example of something not realted to astronomy was an augmented reality application I had in mind for which I wanted the application to shade the models projected on the screen according to the location of the sun. One of the astronomy related applications is that I have access to a room with projectors and screens on all 4 walls. Just for the fun of it I wanted to to get the computers that control the projectors on all 4 walls communicating with each other and displaying a 360 view of the solar system. Getting the sidereal time is a stepping stone for some of these other applications but not the end goal itself. I plan to write on how these other ideas progress as each one of them gets implemented.

Figures and Illustrations

Revision History

  • 2012-09-14 - Initial publication

 

 

 

 

Windows Phone 8 Marketplace for 180 Countries

We've come a long way since Microsoft initially launched it's mobile Marketplace. The original Windows Marketplace for Mobile was available to about 30 nations. If you didn't live in one of those nations and you wanted an application that was only distributed through the Marketplace then there was no way to get it. On Windows Phone 7 (unlike Windows Mobile) the Marketplace was the *only* way to load programs, so the implications were even different. At the time of this writing Microsoft has the Marketplace available in 60 countries. But they have  recently announced that the Marketplace for Windows Phone 8 will be available in 180 countries and will make in-app purchasing available (increasing your opportunity for making money). 

Source: Windows Phone Team Blog

RestSharp and Windows Metro

I've got RestSharp (partially) working on Windows Metro. I've been able to make a simple Metro application and make a few rest calls. Though right now some encryption and signature related functionality isn't yet working. 

I can't seem to run the unit test in Visual Studio 11 and may try to resolve that later this week. But if you want to take a look at my changes thus far you can find them on github.com

https://github.com/j2inet/RestSharp

 

Compiling Same Code on Windows Phone 7 and Windows 8 Metro

Download Code (1.14 MB)

I was thinking about how to write code that will work on both Windows Phone 7 and Windows 8 (Metro). In theory some of the techniques that could be used are well known. But I wanted to try them out. So I decided to try some things out in a piece of throw away code. This gives me some liberty to experiement without worrying about the long term consequences of having not chosen the "best" way. For my throw away application I decided to make an application that would grab some one's Facebook friend list and display it on the screen. So this code will necessarily need to authenticate the user against Facebook. If you've not worked with the Facebook APIs before don't worry about it too much. You should still be able to follow along since this isn't digging deeply into what's available.

I've managed to use some of the techniques to make a Windows Metro version of RestSharp. I'll talk about that in another post.

Register your Application

Before you begin doing any coding you'll want to register your new Facebook application in the Facebook developer portal. This also means that you need to have a facebook account. Because I didn't want to bother my associates with test items in my feed I also created a secondaty facebook account for testing. The portal is available at developer.facebook.com. Clicking on menu item "Apps" at the top of the screen will take you to a page that shows all of your registered applications (if any) and will let you register more. If this is your first time using the portal you'll have no applications. I'll walk you through registering an application. I'll only draw your attention to options as necessary. Options that I don't mention can be left in their default state (which will most likely be blank).

Click on the "Create New App" button. You'll get prompted with a dialog in which you will need to enter the name of the application that you are creating. The dialog will automatically validate the name that you've entered once you've stopped typing and will let you know if a chane needs to be made. Once you have a name that the dialog considers valid click on the "Continue" button.

The next dialog is a Captcha. I really dislike Captchas. While I understand that these dialogs exists to make sure that a bot is not registering the new application the problem that I have with them is that more times than not I'm going to get the entry wrong a few times (ex: is that third character a lowercase 'L', upper case 'L', or an uppercase 'I'?).

Once you pass the Captcha you'll get an opportunity to specify the other details for your application and a chance to change the application's icon and category. It may not be obvious which option to select for "Select how your app integrates with Facebook." None of the available options has a description that you would automatically assocate with a Windows Phone or Metro application. Select "Website". During development it doesn't matter if the website that you've specified exists or not. But you will need to enter an address to a page that would  in theory process the login information. Once you've entered this information select "Save Changes." There are three pieces of information that are on this page that you'll be copying into your application later on: App ID, App Secret, and the Site URL. Keep this page open so that you can copy the information when I refer to it later.

 

 

Now to make your mobile application. At the time of this writing you'll need to use Visual 2010 for Windows Phone applications and Visual Studio 11 for Windows Metro applications. Most of what will be done will be similar enough such that I can talk about the procedure to be followind in parallel and note the occasional differences as they arise.

Creating the New Application Projects

I created both a Silverlight Application for Windows Phone and a Windows 8 Metro project. There are going to be significant blocks of code that will be identical between these two projects. When this occurs I'll only create one version of the file but will have it referenced in both projects. Linked files can easily be recognized by the arrow that shows in the lower-left corner of their icon. If you've never linked files before you can find more information on it here.

How linked files appear in Visual Studio.

Conditionally Compiled Code

There still may be sections in thee files that are specific to Windows Phone or Windows 8. These sections will be conditionally commented out depending on the platform on which the code is being compiled. For code that is specific to Windows 8 Metro applications the code is wrapped in #if NETFX_CORE/#endif blocks. For Windows 7 code I've wrapped the code in #if SILVERLIGHT/#endif blocks. I could have also used #if WINDIWS_PHONE/#endif blocks

If there is a large block of code that is specific to one platform and not the other instead of using the conditional compilation directives one could choose to just include the file containing the code in one file and not in the other. You'll see this done with most of the UI code (the XAML, while similar, is not shared between the two projects).

Creating the Authentication Page

Before I can call any method in Facebook I need to authenticate the user. Facebook uses a form of open authentication. So we will need to use a web browser in the application. Add a new page to your project caled "AuthenticationPage.xaml." The only element that is necessary in this page will be the web browser.  Many of the differences that you will encounter between Metro and Windows Phone 7 are in UI related code. There's a slight difference in the element that needs to be used for representing a browser element.

 <WebView 
     x:Name="AuthenticationWindow" 
     HorizontalAlignment="Stretch" 
     VerticalAlignment="Stretch"
     LoadCompleted="AuthenticationWindow_LoadCompleted" 
/>
 
<phone:WebBrowser  
   Name="AuthenticationWindow" 
   HorizontalAlignment="Stretch"
   VerticalAlignment="Stretch" 
   Navigated="AuthenticationWindow_Navigated" 
/>
Browser element for Windows Metro
 
Browser element for Windows Phone 7

The Application Constants

There are a few elements of data to which we will need. They are all in the entries for the app that you registered with Facebook. I'll need to use these in more than one place. The logic needed for authentication is simple and I left it in the UI code.  I separated the logic that will be shared in the Metro and WP7 versions of this application into a partial class definition. That

static class ApplicationConstants
{
	const string REDIRECT_URL = "https://mysite.com/SomePostAuthenticationPage.html";
	const string APP_ID = "_YOUR_APP_ID_";
	const string APP_SECRET = "_YOUR_APP_SECRET_";
	const string PERMISSIONS = "read_friendlists";
}

You'll need to substitute the values for your own application in these constants (except for the PERMISSIONS constant).

Creating the Authentication Page

An extremely high level overview of what occurs in the code-behind for the authentication page is that it will load the Facebook Open Authentication page and then monitor the path to which the user navigates. If the user has authenticated the browser will be directed to the site that had been registered for the application earlier. When this occurs there will be an authentication code appended to the URL. That code will be parsed out and exchanged for a token. There's not much the UI is really doing. So the codebehind looks simple. 

public partial class AuthenticationPage : PhoneApplicationPage
{
   public AuthenticationPage()
   {
      InitializeComponent();
      ViewModel = (App.Current as J2i.Net.FacebookAuthenticationTest.App).ViewModel;
      ViewModel.AuthenticationAttempted = true;
   }

   private void AuthenticationWindow_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
   {
   }

   private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
   {  
      PrepareForAuthentication();
   }

   private void AuthenticationWindow_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
   {
   }

   private void AuthenticationWindow_Navigating(object sender, NavigatingEventArgs e)
   {
      ProcessWebPageLoad(e.Uri.ToString());
   }
}
Code-behind for the Windows Phone version of the application

Handling Code Differences with Partial Classes

Where there is a slight difference in the code behind for the two pages the rest of the logic is the same. Instead of duplicating it I put the common logic in a partial class definition. The partial class has the same name as the class for the page. So at compile time the code from the code-behind and the partial class will be compiled into a single class. The common code is in AuthenticationPage.xaml.shared.cs.  The first method that the code-behind references from the shared file is PrepareForAuthentication(). This method will build the authentication URL which contains parameters to allow the application to identify itself, what permissions are needed, and a random string that should be passed for security reasone. If you want to see more information on these parameters they can be found in the Facebook authentication documentation.

void PrepareForAuthentication()
{
    _unique = Guid.NewGuid().ToString();

    string targetUrl = String.Format("https://www.facebook.com/dialog/oauth?" +
                                        "client_id={0}" +
                                        "&redirect_uri={1}" +
                                        "&scope={2}" +
                                        "&state={3}",
                                        // for touch/phone friendly version of the authentication page
                                        //"&display=touch",
                                        Uri.EscapeUriString(ApplicationConstants.APP_ID),
                                        Uri.EscapeUriString(ApplicationConstants.REDIRECT_URL),
                                        Uri.EscapeUriString(ApplicationConstants.PERMISSIONS),
                                        Uri.EscapeUriString(_unique));
    AuthenticationWindow.Navigate(new Uri(targetUrl));
}

The ProcessWebPage() method looks at the URL to which the browser is navigating to see whether or not it is our redirect URL. If it's not then nothing happens. If it is then the query parameters are extracted. Theparameters we are most interested in are code and state since these will indicate a successful authentication attempt. The code will be needed to request an access token for making Facebook API calls.

void ProcessWebPageLoad(string targetUriString)
{
   if (targetUriString.IndexOf(ApplicationConstants.REDIRECT_URL) == 0)
   {

      string _code = GetQueryParam(targetUriString, "code");
      string _state = GetQueryParam(targetUriString, "state");
      string _error = GetQueryParam(targetUriString, "error");
      string _errorReason = GetQueryParam(targetUriString, "error_description");
      string _errorDescription = GetQueryParam(targetUriString, "error_reason");

      if (
         (!String.IsNullOrEmpty(_code)) &&
         (!String.IsNullOrEmpty(_state)) &&
         (_unique.Equals(_state))
      )
      {
         ExchangeCodeForAccessToken(_code);
      }
   }
}

Requessting the access token is another web call, but it's not one for which we need the browser. It doesn't return anything user friendly so we can make the call without using the browser. Getting the access token is just a matter of building a URL and grabbing the token from the results.

void ExchangeCodeForAccessToken(string code)
{
    //Building the Request URL
    string targetUrl = String.Format("https://graph.facebook.com/oauth/access_token?" +
                                        "client_id={0}" +
                                        "&redirect_uri={1}" +
                                        "&client_secret={2}" +
                                        "&code={3}",
                                        Uri.EscapeUriString(ApplicationConstants.APP_ID),
                                        Uri.EscapeUriString(ApplicationConstants.REDIRECT_URL),
                                        Uri.EscapeUriString(ApplicationConstants.APP_SECRET),
                                        Uri.EscapeUriString(code));
    var webRequest = HttpWebRequest.CreateHttp(targetUrl);

    //Request the URL
    webRequest.BeginGetResponse((o) =>
    {
        //Stuff the response into a string
        var response = webRequest.EndGetResponse(o);
        var rs = response.GetResponseStream();
        StreamReader sr = new StreamReader(rs);
        var responseString = sr.ReadToEnd();

        //Get the access token and its expiration date
        string accessToken = GetQueryParam(responseString,"access_token");
        DateTime expirationDate = DateTime.MinValue;
        string expiresString = GetQueryParam(responseString, "expires");

        if (!String.IsNullOrEmpty(expiresString))
        {
            int expireTime;
            if (int.TryParse(expiresString, out expireTime))
            {
                expirationDate = DateTime.Now.AddSeconds(expireTime);
            }
        }

        //If we successfully got a token and expiration save them, start grabbing the
        //friend list, and then navigate to the previous page
        if (!String.IsNullOrEmpty(accessToken) && (expirationDate != DateTime.MinValue))
        {
            ViewModel.AccessInfo = new AccessInfo() { ExpirationDate = expirationDate, Token = accessToken };
            ViewModel.SaveAccessToken();
            ViewModel.UpdateFriendList();
            ReturnToPreviousPage();
        }
    }, null);
}

Navigation is a little different on Windows Phone 7 and Windows 8. So I added a ReturnToPreviousPage() method in both the code-behind for the Metro and Windows Phone 7 versions of the application. Each of which contains the appropriate version of the navigation code.

void ReturnToPreviousPage()
{
   ViewModel.DispatchInvoke(() =>
   {
      (Window.Current.Content as Frame).GoBack();

   }
   );
}
 
void ReturnToPreviousPage()
{
   ViewModel.DispatchInvoke(() =>
   {
       NavigationService.GoBack();
   }
   );
}
Windows 8 Metro Version
 
Windows Phone Version

Retreiving the Friend List

The code for retrieving the friend list looks identical on both platforms. Facebook may not return the entire friend list in one call. If there are more friends to be retrieved in the return structure from the call there will be an address in a member in the return structure named Next (nested in Paging) which contains the address to the next page of the results. I'm not parsing the results myself but am instead making use of JSON.Net by James Newton-King. The results are parsed and accumulated into a temporary list. Once I know that I have all the results they are moved to the bindable list that drives the list box on the UI.

public void UpdateFriendList(string targetUrl = null, List previousUserList = null)
{
    if (AccessInfo == null)
        return;
    if (previousUserList == null)
        previousUserList = new List();

    var request = System.Net.HttpWebRequest.CreateHttp(targetUrl ?? String.Format(FRIEND_LIST_REQUEST, AccessInfo.Token));
    request.BeginGetResponse((o) =>
        {
            var response = request.EndGetResponse(o);
            var responseStreamReader = new StreamReader(response.GetResponseStream());
            string friendListText = responseStreamReader.ReadToEnd();
            Newtonsoft.Json.JsonSerializer s = new JsonSerializer();
            Data.FriendListResponse v = Newtonsoft.Json.JsonConvert.DeserializeObject(friendListText);
            if ((v != null) && (v.Data != null))
            {
                foreach (var user in v.Data)
                {
                    previousUserList.Add(user);
                }
            }
            if ((v!=null) && (v.Paging != null) && (v.Paging.Next != null))
                UpdateFriendList(v.Paging.Next, previousUserList);
            else
            {
                previousUserList.Sort((a1, a2) => { return a1.Name.CompareTo(a2.Name); });
                DispatchInvoke(() =>
                    {
                        FriendList.Clear();
                        foreach (var u in previousUserList)
                            FriendList.Add(u);
                    }
                );
            }

        }, null);
}

Dispatching Differences

There is a rule in Windows Platforms that you cannot modify the UI from a seconday thread. On the XAML based platforms you can ensure calls that modify the UI are marshalled to the UI thread by making use of an object called the Dispatcher. The way that you use this object differs on Windows Phone 7 and Windows 8. I abstracted away the differences by making a method called DispatchInvoke(). It compiles different on each platform and will call the appropriate code on each platform.

public void DispatchInvoke(Action a)
{
#if SILVERLIGHT
    if (MainViewModel.Dispatcher == null)
        a();
    else
        Dispatcher.BeginInvoke(a);
#else
    if ((Dispatcher != null) && (!Dispatcher.HasThreadAccess))
    {
        Dispatcher.InvokeAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, (obj, invokedArgs) => { a(); }, this, null);
    }
    else
        a();
#endif
}

Saving Data

For saving simple data types I tend to use a simple component that I made for Windows Phone 7 (it can be found here). On Windows 8 all file IO is asynchronous. So the component had to be modified to work on Metro. I've shown the details of the changes on another page. Since the Windows Phone 7 version uses a blocking call and the Metro version is asynchronous the calls could not be made to look the same. But this difference was compatmentalized to a single method.

public void SaveAccessToken()
{
   if (this.AccessInfo != null)
   {
#if NETFX_CORE
      DataSaver<AccessInfo>.SaveMyDataAsync(this.AccessInfo, "_accessToken.xml");
#endif
#if SILVERLIGHT
     DataSaver<AccessInfo>.SaveMyData(AccessInfo, "_accessToken.xml");
#endif
   }
}

Most of the code for this project is in the MainViewModel class. The entirity of the code for it is below. It shouldn't contain anything that you don't recognize from above. The using directives at the top contain conditional compilation directives since the namespaces in which some of the classes exists differs on Windows Phone 7 and on Windows 8 Metro.

using System;
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using Newtonsoft.Json;
using J2i.Net.FacebookAuthenticationTest.Data;
using J2i.Net.FacebookAuthenticationTest.Utility;


#if SILVERLIGHT
using System.Windows.Threading;
#endif

#if NETFX_CORE
using System.Threading.Tasks;
using J2i.Net.FacebookAuthenticationTest.Data;
using Windows.UI.Xaml;

#endif

namespace J2i.Net.FacebookAuthenticationTest.ViewModel
{
    public class MainViewModel: INotifyPropertyChanged 
    {
        const string FRIEND_LIST_REQUEST = "https://graph.facebook.com/me/friends?access_token={0}";


        public MainViewModel()
        {
#if SILVERLIGHT
            var a = DataSaver<AccessInfo>.LoadMyData("_accessToken.xml");
            if(a !=null)
            {
                this.AccessInfo = a;
                this.UpdateFriendList();
            }
#endif

#if NETFX_CORE
            DataSaver<AccessInfo>.LoadDataAsync("_accessToken.xml", (info, exc)=>
            {
                if (info != null)
                {
                    this.AccessInfo = info;
                    this.UpdateFriendList();
                }
            });
#endif
        }

        ObservableCollection<FacebookUser> _friendList;
        public ObservableCollection<FacebookUser> FriendList
        {
            get { return (_friendList) ?? (_friendList = new ObservableCollection<FacebookUser>()); }
            set { _friendList = value; }
        }
 

        string _friendListText = String.Empty;
        public string FriendListText
        {
            get { return _friendListText; }
            set 
            {
                if (value != _friendListText)
                {
                    _friendListText = value;
                    RaisePropertyChanged("FriendListText");
                }
            }
        }


        public void SaveAccessToken()
        {
            if (this.AccessInfo != null)
            {
#if NETFX_CORE
                DataSaver<AccessInfo>.SaveMyDataAsync(this.AccessInfo, "_accessToken.xml");
#endif
#if SILVERLIGHT
               DataSaver<AccessInfo>.SaveMyData(AccessInfo, "_accessToken.xml");
#endif
            }
        }

        AccessInfo _accessInfo;
        public AccessInfo AccessInfo
        {
            get { return (_accessInfo) ?? (_accessInfo = new AccessInfo()); }
            set 
            {
                if (_accessInfo != value)
                {
                    _accessInfo = value;

                }
            }
        }

        bool _authenticationAttempted = false;
        public bool AuthenticationAttempted
        {
            get { return _authenticationAttempted || (!String.IsNullOrEmpty(AccessInfo.Token)); }
            set { _authenticationAttempted = value; }
        }

#if NETFX_CORE
        static Windows.UI.Core.CoreDispatcher _dispatcher;
        public static Windows.UI.Core.CoreDispatcher Dispatcher
        {
            get
            {
                if (_dispatcher != null)
                    return _dispatcher;
                if ((Window.Current==null)||(Window.Current.Content == null))
                    return null;
                return Window.Current.Content.Dispatcher; 
            }
            set { _dispatcher = value; }
        }
#endif

#if SILVERLIGHT
        static Dispatcher _dispatcher;
        public static Dispatcher Dispatcher
        {
            get
            {
                if (_dispatcher!=null)
                    return _dispatcher;
                var app = (App.Current as J2i.Net.FacebookAuthenticationTest.App);
                if (app.RootFrame == null)
                    return null;
                return (app.RootFrame.Dispatcher);
            }
            set
            {
                _dispatcher = value;
            }
        }    
#endif


        public void UpdateFriendList(string targetUrl = null, List<FacebookUser> previousUserList = null)
        {
            if (previousUserList == null)
                previousUserList = new List<FacebookUser>();

            var request = System.Net.HttpWebRequest.CreateHttp(targetUrl ?? String.Format(FRIEND_LIST_REQUEST, AccessInfo.Token));
            request.BeginGetResponse((o) =>
                {
                    var response = request.EndGetResponse(o);
                    var responseStreamReader = new StreamReader(response.GetResponseStream());
                    string friendListText = responseStreamReader.ReadToEnd();
                    Newtonsoft.Json.JsonSerializer s = new JsonSerializer();
                  Data.FriendListResponse v = Newtonsoft.Json.JsonConvert.DeserializeObject<Data.FriendListResponse>(friendListText);
                  if ((v != null) && (v.Data != null))
                  {
                      foreach (var user in v.Data)
                      {
                          previousUserList.Add(user);
                      }
                  }
                  if ((v!=null) && (v.Paging != null) && (v.Paging.Next != null))
                      UpdateFriendList(v.Paging.Next, previousUserList);
                  else
                  {
                      previousUserList.Sort((a1, a2) => { return a1.Name.CompareTo(a2.Name); });
                      DispatchInvoke(() =>
                          {
                              FriendList.Clear();
                              foreach (var u in previousUserList)
                                  FriendList.Add(u);
                          }
                      );
                  }

                }, null);
        }


        void DispatchInvoke(Action a)
        {
#if SILVERLIGHT
            if (MainViewModel.Dispatcher == null)
                a();
            else
                Dispatcher.BeginInvoke(a);
#else
            if ((Dispatcher != null) && (!Dispatcher.HasThreadAccess))
            {
                Dispatcher.InvokeAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, (obj, invokedArgs) => { a(); }, this, null);
            }
            else
                a();
#endif
        }
        protected void RaisePropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
            {
                DispatchInvoke(()=>
                    {
                        RaisePropertyChanged(propertyName);
                    });
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

Invoking through the Dispatcher on Windows Phone and Metro

Note: : Between the time that I wrote this and final release there were changes to the Windows Store Runtime. InvokeAsync nolonger exists. It has been replaced with RunAsync. Change noted below.

On the Windows Platforms there is a rule that you cannot modify UI elements from secondary threads. On Microsoft's XAML based platforms there is a member that exists on most UI objects called the Dispatcher that can be used to marshal a call to the proper thread.

On Windows Phone 7 and Windows 8 the way you go about calling this thread differs. I was recently working with some code that needed to compile for both platforms and wanted to minimize the amount of code that had to be wrapped in conditional compilation blocks. To do this I made a single method to handle my dispatching. The method itself contains conditional compilation blocks but because of this method I didn't need the blocks when I needed perform operations on the UI thread.

public void DispatchInvoke(Action a)
{
#if SILVERLIGHT
    if (Dispatcher == null)
        a();
    else
        Dispatcher.BeginInvoke(a);
#else
    if ((Dispatcher != null) && (!Dispatcher.HasThreadAccess))
    {
        Dispatcher.InvokeAsync( //RTM change
        Dispatcher.RunAsync(
                    Windows.UI.Core.CoreDispatcherPriority.Normal, 
                    (obj, invokedArgs) => { a(); }, 
                    this, 
                    null
         );
    }
    else
        a();
#endif
}

The code will compile for both Windows Phone 7 and Windows 8 Metro without any alterations. Using the code is the same regardless of which of the two platforms that you are using.

DispatchInvoke(()=>
  {
    //your operations go here
    TextBox1.Text="My Text";
  }
);

Data Serializer updated for Windows Metro

About a year ago I shared a simple utility class for saving serializable data on Windows Phone 7. I just updated the component for Windows 8 Metro. It still retains compatibility with Windows Phone 7 through the use of conditional compiler directives. On Windows Phone 7 I've changed the class so that it is static (so no need to instantiate it). 

For Metro the methos are asynchronous.  For saving an action can be passed that will be called once the save operation is complete. When loading data you'll want to pass an action that will received the loaded data and an exception parameter that will be populated if the data could not be loaded. 

 

As an example of how the code works (and the platform dependent differences in its usage) here is a method from a program I have that is using the code. The program compiles on both Windows Phone 7 and Windows Metro.

        public void LoadAccess()
        {
#if SILVERLIGHT
            AccessInfo = DataSaver<AccessInfo>.LoadMyData("_accessToken.xml");
#endif

#if NETFX_CORE
            DataSaver<AccessInfo>.LoadDataAsync("_accessToken.xml", (info, exc)=>
            {
                if (info != null)
                {
                    this.AccessInfo = info;
                }
            });
#endif
        }

        public void SaveAccessToken()
        {
            if (this.AccessInfo != null)
            {
#if NETFX_CORE
                DataSaver<AccessInfo>.SaveMyDataAsync(this.AccessInfo, "_accessToken.xml");
#endif
#if SILVERLIGHT
               DataSaver<AccessInfo>.SaveMyData(AccessInfo, "_accessToken.xml");
#endif
            }
        }

If you've never seen the #if/#endif directives before it is used to essentially conditionally comment out sections of code based on some condition. In this case the condition is certain compiler constants being defined. Some constants are automatically created for various project types. If you create a windows phone project the WINDOWS_PHONE and SILVERLIGHT constants are defined. For a Windows 8 Metro project the NETFX_CORE constant is defined. When you are viewing the code in the Visual Studio IDE it will gray out any code that is going to be ignored because of the conditional compilation statements. 

Below is the code for the serializer. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;

using System.IO;
#if SILVERLIGHT
using System.IO.IsolatedStorage;
#endif

#if NETFX_CORE
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;
#endif

namespace J2i.Net.FacebookAuthenticationTest.Utility
{


    public class DataSaver<MyDataType>
    {

        static List<Type> _knownTypeList = new List<Type>();
        public static List KnownTypeList
        {
            get
            {
                return _knownTypeList;
            }
        }
#if SILVERLIGHT
        private static IsolatedStorageFile _isoFile;
        static IsolatedStorageFile IsoFile
        {
            get
            {
                if (_isoFile == null)
                    _isoFile = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication();
                return _isoFile;
            }
        }

         public static void SaveMyData(MyDataType sourceData, String targetFileName)
        {
            try
            {
                using (var targetFile = IsoFile.CreateFile(targetFileName))
                {
                    var d = new DataContractSerializer(typeof(MyDataType), KnownTypeList);
                    d.WriteObject(targetFile, sourceData);
                }
            }
            catch (Exception )
            {
                IsoFile.DeleteFile(targetFileName);
            }
        }


        public static MyDataType LoadMyData(string sourceName)
        {
            MyDataType retVal = default(MyDataType);
            if (IsoFile.FileExists(sourceName))
                using (var sourceStream = IsoFile.OpenFile(sourceName, FileMode.Open))
                {
                    var d = new DataContractSerializer(typeof(MyDataType), KnownTypeList);
                    retVal = (MyDataType)d.ReadObject(sourceStream);
                }
            return retVal;
        }
#endif
        public DataSaver()
        {
        }
#if NETFX_CORE
        public static async void SaveMyDataAsync(
            MyDataType sourceData, 
            String targetFileName, 
            Action<MyDataType,String, Exception> OnSaved = null)
        {
            try
            {
                StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(
                    targetFileName, CreationCollisionOption.ReplaceExisting
                    );
                IRandomAccessStream raStream = await file.OpenAsync(FileAccessMode.ReadWrite);
                IOutputStream outStream = raStream.GetOutputStreamAt(0);

                DataContractSerializer serializer = new DataContractSerializer(typeof(MyDataType), KnownTypeList);
                serializer.WriteObject(outStream.AsStreamForWrite(), sourceData);
                await outStream.FlushAsync();
                if(OnSaved!=null)
                    OnSaved(sourceData, targetFileName, null);
            }
            catch (Exception exc)
            {
                if (OnSaved != null)
                {
                    OnSaved(sourceData, targetFileName, exc);
                }
            }
        }

        public static async void LoadDataAsync(string fileName, Action<MyDataType, Exception> loadAction)
        {
            if (loadAction == null)
                return;
            try
            {
                StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
                if (file == null) return;
                IInputStream inStream = await file.OpenSequentialReadAsync();

                // Deserialize the Session State. 
                DataContractSerializer serializer = new DataContractSerializer(typeof(MyDataType), KnownTypeList);
                MyDataType data = (MyDataType)serializer.ReadObject(inStream.AsStreamForRead());
                loadAction(data, null);
            }
            catch (Exception e)
            {
                loadAction(default(MyDataType), e);
            }
        }
#endif

    }
}

Getting Assembly Version Number in WinRT

It seems that every time one makes a shift from one .Net platform to another the method you use to reflect the version number for an assembly changes. I needed to get this information for a WinRT program earlier and was able to do so with a regular expression and the slightly different reflection methods in WinRT. The code follows:

 

var asmName = this.GetType().AssemblyQualifiedName;
var versionExpression = new System.Text.RegularExpressions.Regex("Version=(?<version>[0-9.]*)");
var m = versionExpression.Match(asmName);
string version = String.Empty;
if (m.Success)
{
    version = m.Groups["version"].Value;
}