Documentation

Building the service

To build the service, you can either launch the Visual Studio solution from a Robotics Studio command environment or, at the very least, ensure that the environment variable MRI_INSTANCE_DIR points to the root of your Robotics Studio install. By default on a Windows 7 box, this should be “%HOMEDRIVE%%HOMEPATH%\Microsoft Robotics Dev Studio 2008 R3”. Building the project should sign the binaries with the Robotics Studio sample key, and automatically place the service & proxy binaries in the Robotics Studio \bin folder to be picked up by other services.

When you use the service in other projects, be sure to add a reference to the proxy DLL, SoCGadget.XBeeService.Proxy.dll, and not the main DLL.

Usage tutorial

The service supports several operations to send messages to and receive data from XBee end point devices. Probably the best way to demonstrate its use is through code samples. In order to run this example, you will need two XBee devices, one connected to a USB port of your PC running Robotics Studio, the other connected to up to a display of some sort so that you can see the message coming across. I have documented an Arduino project here that does just that if you want some ideas. Set one XBee up as a coordinator, this gets plugged into the PC, and the other up as an end device. Make sure to make note of the serial number of  the end device (SH, SL values). This will be used as a target address. The service only uses XBee's 64-bit network address mode and not the 16-bit mode. Finally, I set both up to operate in API Operation Escaped mode.

Make sure you have one of the editions of Visual Studio 2010 (such as C# Express) and Microsoft Robotics Studio 2008 R3 installed on your PC. Download the zip file of the XBeeService and unzip it inside the Robotics Studio \bin folder.

Start a new project in Visual Studio and under the Installed Templates, select Visual C#->Microsoft Robotics. You should see the project type DSS Service (2.2) show up. Also insure .NET Framework 3.5 is selected. Give your project a name (I chose XBeeServiceTest) and click OK.

You are now presented with the New DSS Service dialog. On the Service tab, the defaults are fine. Select the Partners tab. Under Services, look for the SoCGadget XBeeService entry and select it. Click ‘Add as partner’. Under Creation policy, UseExistingOrCreate is fine, and be sure to check ‘Add notification port’.

NewDSSService

Select OK to create the project.

The service’s source file XBeeServiceTest.cs should open automatically (the name may vary depending on what you named your project) but if not, open it now in the Visual Studio editor. You should see the following alias already defined for you, along with the XBeeServiceOperations ports shown below:

// Ensure the following aliases are defined
using xbee = SoCGadget.Robotics.XBee.Proxy;

/// <summary>
/// XBeeService partner
/// (Created for you by Visual Studio)
/// </summary>
[Partner( "XBeeService", Contract = xbee.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExistingOrCreate )]
xbee.XBeeServiceOperations _xBeeServicePort = new xbee.XBeeServiceOperations();
xbee.XBeeServiceOperations _xBeeServiceNotify = new xbee.XBeeServiceOperations();

Create a handler that will receive event data update notifications from XBee end devices on the network

// Create a handler to get the data sample received notifications
private void XBeeServicevDataSampleUpdateHandler( xbee.DataSampleUpdate message )
{
    // Log digital I/O
    for ( int i = 0; i < message.Body.DigitalChannelMask.DIO.Length; i++ )
    {
        if ( message.Body.DigitalChannelMask.DIO[ i ] )
        {
            LogInfo( string.Format( "DIO{0} = {1}", i, message.Body.DigitalIO.DIO[ i ] ) );
        }
    }

    // Log analog I/O
    // I use Length - 1 to not pick up supply voltage reading. I do that seperately below.
    for ( int i = 0; i < message.Body.AnalogChannelMask.DIO.Length - 1; i++ )
    {
        if ( message.Body.AnalogChannelMask.DIO[ i ] )
        {
            double Vin = ( double )( message.Body.AnalogIO[ i ] * 1200 / 1024 ) / 1000.0;
            LogInfo( string.Format( "ADC{0} = {1}V", i, Vin ) );
        }
    }

    // Log supply voltage
    if ( message.Body.SupplyVoltage > 0 )
    {
        double Vcc = ( double )message.Body.SupplyVoltage / 1000.0;
        LogInfo( string.Format( "Supply voltage = {0}V", Vcc ) );
    }
}

Now, inside your Start() routine, add the following code to tie your event handler to the notifications port and then subscribe to the XBeeService notifications.

protected override void Start()
{
    // Add notifications to the main interleave
    base.MainPortInterleave.CombineWith(
        new Interleave(
            new ExclusiveReceiverGroup(),
            new ConcurrentReceiverGroup(
            Arbiter.Receive<xbee.DataSampleUpdate>(
                true, _xBeeServiceNotify, XBeeServicevDataSampleUpdateHandler )
            )
        )
    );

    // Subscribe to event notifications
    _xBeeServicePort.Subscribe( _xBeeServiceNotify );

The last thing we'll put in the Start() method is a line of code to kick off a task that will send a test message to our XBee end point.

    Arbiter.Activate(
        new DispatcherQueue( "my queue", new Dispatcher() ),
        new ITask[] { Arbiter.FromIteratorHandler( TestXBee ) }
    );

Now lets implement the TestXBee iterator method. We'll start by sending a Connect message to our XBee coordinator device.

private IEnumerator<ITask> TestXBee()
{
    xbee.ConnectRequest request = new xbee.ConnectRequest { Baud = 9600, ApiMode = "ApiOperationEscaped" };
    xbee.Connect connect;
    yield return _xBeeServicePort.Connect( request, out connect );
    yield return Arbiter.Choice<DefaultUpdateResponseType, W3C.Soap.Fault>( connect.ResponsePort,
        delegate( DefaultUpdateResponseType response )
        {
            // Success
        },
        delegate( W3C.Soap.Fault fault )
        {
            LogError( fault );
        }
    );

Note that I did not specify a COM port to the connect request operation. This lets the XBeeService search for the XBee device instead of needing to know ahead of time where it is (I got really tired of looking it up in Device Manager).

Now lets send a text message to an end device. First, build up an XBeeAddress64 object to point to our end device. We are using the XBee’s 64-bit addressing mode so the low/high address values are the serial number low/high values of the end device (SL, SH). The hex numbers here are my device's serial numbers, yours will be different.

    xbee.XBeeAddress64 endPointAddr = new xbee.XBeeAddress64
    {
        AddressHigh = 0x13a200,
        AddressLow = 0x4030d088
    };

Now let’s send a message!

    xbee.DeviceMessage xbeeMsg = new xbee.DeviceMessage
    {
        DestinationAddress = endPointAddr,
        Message = "Hello XBee!"
    };

    xbee.DeviceMessageUpdate update;
    yield return _xBeeServicePort.DeviceMessageUpdate( xbeeMsg, out update );
    yield return Arbiter.Choice<DefaultUpdateResponseType, W3C.Soap.Fault>( update.ResponsePort,
        delegate( DefaultUpdateResponseType response )
        {
            // Success
        },
        delegate( W3C.Soap.Fault fault )
        {
            LogError( fault );
        }
    );

Finally, we’ll disconnect from the coordinator XBee in the shutdown method:

protected override void Shutdown()
{
    xbee.Disconnect disconnect;
    if ( _xBeeServicePort != null )
    {
        _xBeeServicePort.Disconnect( new xbee.DisconnectRequest(), out disconnect );
    }

    base.Shutdown();
}

Press F5 in Visual Studio and in a few seconds, it will send the text string to your XBee end device. I don’t go into details here but you can configure your XBee end device to send notifications when data changes on one of its I/O ports. If you do this, you will receive that notification in your notification handler in your service and can act on it appropriately.

Setting digital outputs

Last edited Oct 16, 2011 at 2:35 AM by jmckelvey, version 16

Comments

No comments yet.