Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Задани на лабораторные работы. ПРК / Professional Microsoft Robotics Developer Studio

.pdf
Скачиваний:
125
Добавлен:
20.04.2015
Размер:
16.82 Mб
Скачать

www.it-ebooks.info

Chapter 3: Decentralized Software Services (DSS)

Running the Services Together

Recompile both ServiceA and ServiceB. Then run ServiceA in the debugger. If you have done everything properly, then Service B should also start up, as shown in Figure 3-22.

Figure 3-22

If you read through the output in Figure 3-22, you will see that ServiceB is created by ServiceA, but the first Get response from ServiceB is before it has output any “sensor” readings, and consequently the value is zero. (The first “reading” is when ServiceB displays B: 64).

After 10 iterations, the timer interval for ServiceB is changed by ServiceA. Then you see sensor readings doubling up because ServiceA continues to poll ServiceB at the same rate as before. This is now too fast for the incoming “sensor data” at the ServiceB end.

Lastly, ServiceA tells ServiceB to shut down by sending a Drop message.

143

www.it-ebooks.info

Part I: Robotics Developer Studio Fundamentals

Using the Partner Attribute to Start Services

Rather than create services explicitly, you can create a service partner declaratively using the [Partner]attribute. This is the usual approach. However, sometimes you do not know ahead of time what services you will have to partner with — for example, the Dashboard dynamically partners with Differential Drive services, Laser Range Finder services, and Webcam services. When it starts, it doesn’t know which of these services might be available. More to the point, it doesn’t know which DSS node you are going to point it at.

To specify a partner at compile time, go back to the top of ServiceA.cs and change the declaration of _servicebPort as follows:

// Partner with ServiceB

[Partner(“ServiceB”, Contract = serviceb.Contract.Identifier,

CreationPolicy = PartnerCreationPolicy.CreateAlways, Optional = false)] private serviceb.ServiceBOperations _servicebPort =

new serviceb.ServiceBOperations();

Notice that the contract identifier for ServiceB is specified as a parameter to the [Partner] attribute. In addition, ServiceB is not optional. The CreationPolicy is set to CreateAlways. This causes the constructor service to create a new instance of ServiceB for you. It doesn’t matter whether you create a new instance of the service operations port or leave it null if the config file exists because the State service will take care of it.

Four service creation policies are available:

CreateAlways

UseExistingOrCreate

UseExisting

UsePartnerListEntry

The simplest approach is CreateAlways. This is equivalent to creating the service explicitly but requires only a couple of lines of code. In some cases this makes sense, such as when a service uses another service that is never called directly by anyone else, i.e., there is a one-to-one partnership.

Now that you have declared the partnership with ServiceB, there is no longer any need to call the CreatePartner routine. However, for the purposes of illustrating a point, you will insert some different code.

The FindPartner routine replaces CreatePartner:

private IEnumerator<ITask> MainTask()

{

Port<EmptyValue> done = new Port<EmptyValue>();

SpawnIterator<Port<EmptyValue>>(done, FindPartner);

144

www.it-ebooks.info

Chapter 3: Decentralized Software Services (DSS)

FindPartner issues a DirectoryQuery to try to find ServiceB, but with the default long timeout:

private IEnumerator<ITask> FindPartner(Port<EmptyValue> p)

{

// Find ServiceB in the local directory Console.WriteLine(“Finding ServiceB in the Directory”); yield return Arbiter.Choice(

DirectoryQuery(serviceb.Contract.Identifier, DsspOperation.DefaultLongTimeSpan),

delegate(ServiceInfoType s)

{

// Request succeeded

LogInfo(LogGroups.Console, “Found ServiceB: “ + s.Service);

Uri addr; try

{

//Create URI from service instance string addr = new Uri(s.Service);

//Now create service forwarder to ServiceB _servicebPort =

ServiceForwarder<serviceb.ServiceBOperations>(addr);

}

catch (Exception ex)

{

LogError(LogGroups.Console, “Could not create forwarder: “ + ex.Message);

_servicebPort = null;

}

},

delegate(W3C.Soap.Fault failure)

{

// Request failed

LogError(LogGroups.Console, “Could not find ServiceB”); _servicebPort = null;

}

);

// Signal that the find is finished p.Post(EmptyValue.SharedInstance);

yield break;

}

Basically, FindPartner waits until ServiceB does a DirectoryInsert and becomes visible in

the service directory. The rest of the code is the same as CreatePartner. This is one way to synchronize service startup. For it to work successfully, services must not call base.Start until they have completed all of their initialization. Otherwise, they appear in the directory prematurely. If you run this revised version of the code, there is not very much difference, so no screenshot is provided.

You can change the partner creation policy to UseExistingOrCreate, but you won’t see any difference in this scenario because the “Or Create” option causes ServiceB to be created. In other words, ServiceA uses an existing instance of ServiceB if one exists; if not, it simply goes ahead and creates one anyway.

145

www.it-ebooks.info

Part I: Robotics Developer Studio Fundamentals

Modifying Manifests Manually

When you create a new service, a manifest is automatically created for you. This section steps you through the process of modifying a manifest using a text editor. However, as you will see later in “Modifying Manifests Using the DSS Manifest Editor,” it is preferable to use the appropriate tool for this task. The purpose of this section is to give you some understanding of what manifests look like and how they work. It is not suggested that you always edit manifests by hand.

Use Existing Partner

In Visual Studio for ServiceA, open ServiceA.manifest.xml. It should have a single service record for ServiceA. Leave it alone for the moment.

Change the partner creation policy in ServiceA.cs to UseExisting:

// Partner with ServiceB

[Partner(“ServiceB”, Contract = serviceb.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.UseExisting, Optional = false)]

private serviceb.ServiceBOperations _servicebPort = new serviceb.ServiceBOperations();

This specifies that there must be a ServiceB running on the DSS node before ServiceA can start up properly. You can see from the ServiceA manifest that there is no mention of ServiceB.

Recompile the code and run ServiceA. Be patient — very patient! In fact, be patient for up to two minutes. Eventually, an error message will appear (displayed in red), as shown in Figure 3-23.

Figure 3-23

This error says, “Partner enumeration during service startup failed.” Quite clearly, the error occurred because you asked for ServiceB but did not create a new instance of it. This is easy to fix.

146

www.it-ebooks.info

Chapter 3: Decentralized Software Services (DSS)

Open the ServiceB.manifest.xml in Visual Studio and copy the Service Record. Then go to ServiceA.manifest.xml and paste it in there. The resulting ServiceA manifest should look like the following:

<?xml version=”1.0” ?> <Manifest

xmlns=”http://schemas.microsoft.com/xw/2004/10/manifest.html”

xmlns:dssp=”http://schemas.microsoft.com/xw/2004/10/dssp.html”

>

<CreateServiceList>

<ServiceRecordType>

<dssp:Contract>http://schemas.tempuri.org/2008/01/servicea.html</dssp:Contract>

</ServiceRecordType>

<ServiceRecordType>

<dssp:Contract>http://schemas.tempuri.org/2008/01/serviceb.html</dssp:Contract>

<dssp:PartnerList>

<dssp:Partner>

<dssp:Service>ServiceB.Config.xml</dssp:Service>

<dssp:Name>dssp:StateService</dssp:Name>

</dssp:Partner>

</dssp:PartnerList>

</ServiceRecordType>

</CreateServiceList>

</Manifest>

Be very careful when you copy and paste pieces of code between XML files. If you end up with mismatched tags, the manifest won’t work at all and you will just get a syntax error. This is one reason why it is better to use the Manifest Editor (discussed in “Modifying Manifests Using the DSS Manifest Editor”), rather than edit manifests manually.

Remember that in the section “Specifying a Configuration File in a Manifest” you added a state service partner to ServiceB. This is part of the Service Record as well. However, when you run ServiceA

now, a new config file is created in the Projects\ServiceA folder because that is where the manifest is. It all gets a little confusing after a while.

This is the brute-force approach to partnering — it simply specifies two services in the manifest and they are both created. Save the manifest and run ServiceA again. The services should now run successfully.

Contract Identifiers and Case Sensitivity

If you have plenty of time and nothing better to do, edit the manifest again by changing the names of the services in the contract identifiers to ServiceA and ServiceB, i.e., capitalize them so that they look pretty. Run ServiceA. What happens? Look at Figure 3-24.

147

www.it-ebooks.info

Part I: Robotics Developer Studio Fundamentals

Figure 3-24

First, the contract directory cache is rebuilt because you requested two services that DSS has not seen before. However, this doesn’t help and you get two error messages saying that there was an error creating the service, with a Fault.Subcode of UnknownEntry.

This is a small trap for beginners — contract identifiers are case-sensitive.

Use Partner List Entry

The last step is to change the partner creation policy to UsePartnerListEntry. Recompile and run ServiceA.

This time you get an error that partner enumeration failed, but ServiceB starts up and begins pumping out “sensor” data. ServiceA, however, does not start.

To fix this problem, you need to edit the manifest and explicitly make ServiceB a partner of ServiceA. The resulting manifest looks like the following, with the changes highlighted:

<?xml version=”1.0” ?> <Manifest

xmlns=”http://schemas.microsoft.com/xw/2004/10/manifest.html”

xmlns:dssp=”http://schemas.microsoft.com/xw/2004/10/dssp.html”

xmlns:this=”http://schemas.tempuri.org/2008/01/servicea.html”

>

<CreateServiceList>

<ServiceRecordType>

<dssp:Contract>http://schemas.tempuri.org/2008/01/servicea.html</dssp:Contract>

<dssp:PartnerList>

<dssp:Partner>

<dssp:Name>this:ServiceB</dssp:Name>

</dssp:Partner>

</dssp:PartnerList>

<Name>this:ServiceA</Name>

148

www.it-ebooks.info

Chapter 3: Decentralized Software Services (DSS)

</ServiceRecordType>

<ServiceRecordType>

<dssp:Contract>http://schemas.tempuri.org/2008/01/serviceb.html</dssp:Contract>

<dssp:PartnerList>

<dssp:Partner>

<dssp:Service>ServiceB.Config.xml</dssp:Service>

<dssp:Name>dssp:StateService</dssp:Name>

</dssp:Partner>

</dssp:PartnerList>

<Name>this:ServiceB</Name>

</ServiceRecordType>

</CreateServiceList>

</Manifest>

Both services have explicit names in the manifest, and ServiceB is in the PartnerList for ServiceA. ServiceB has a config file specified using the StateService as a partner. Note that there is no path, just a filename, so the config file is assumed to be in the same directory as the manifest.

When you run ServiceA with this revised manifest, both services start up and everybody is happy.

DSS Tools

Several tools are supplied with MRDS to assist you with various tasks. You have already seen DssNewService, DssHost, and DssProxy. This section briefly outlines some other tools that you should become familiar with, including the Manifest Editor, DssInfo, and DssProjectMigration. Because it is a significant tool in its own right, DssDeploy is covered in the following section.

Modifying Manifests Using the DSS Manifest Editor

The DSS Manifest Editor was introduced in MRDS V1.5 as a tool to help make the creation and editing of manifests easier. We do not intend to provide a tutorial on the Manifest Editor here, but you should be aware that it exists and read up on it in the online documentation. (Actually, the Manifest Editor is not a separate program but part of VPL. A batch file called dssme.cmd in the MRDS bin directory executes VPL in Manifest mode.)

To try out the Manifest Editor, use the very last manifest from the previous section. You can start the Manifest Editor by clicking Start Microsoft Robotics Studio (1.5) Microsoft DSS Manifest Editor. It might take a little while to start, because it is listing all of the available services.

When the Manifest Editor main screen appears, click File Open and browse to the ServiceA manifest to open it. Once the manifest has been loaded, it should look like what is shown in Figure 3-25.

149

www.it-ebooks.info

Part I: Robotics Developer Studio Fundamentals

Figure 3-25

You can select ServiceB and add an initial configuration if you want. This will add a state partner with a nominated config file.

Apart from that, just play around in the Manifest Editor until you are comfortable with it. You will find it is much easier to use than editing XML files. It is the recommended method for editing manifests, rather than opening them in a text editor.

DssInfo: Examining Contract Information

You can get information about contracts and the operations that a service supports using the DssInfo tool. For example, the following command displays information about the Dashboard service that is included with the code for Chapter 4:

C:\Microsoft Robotics Studio (1.5)>dssinfo bin\dashboard.y2007.m10.dll

You can control the amount of information displayed using command-line qualifiers. The default information level shows the contract, partners, the operations that are supported, and so on, as shown here:

Reflecting:

Dashboard.Y2007.M10.dll

DSS CONTRACT

 

Verbosity

ShowWarnings

Assembly:

c:\microsoft robotics studio (1.5)\bin\dashboar

 

d.y2007.m10.dll

150

www.it-ebooks.info

Chapter 3: Decentralized Software Services (DSS)

Service:

DashboardService

DssContract:

http://www.promrds.com/2007/10/dashboard.html

Namespace:

ProMRDS.Robotics.Services.Dashboard

ServicePrefix:

/dashboard

Singleton:

False

Partner(s):

 

[InitialStatePartner]

/mountpoint/ProMRDS/Config/Dashboard.Config.xml

UseExistingOrCreate

http://schemas.microsoft.com/robotics/2006/09/g

 

amecontroller.html

ServicePort:

DashboardOperations

Lookup:

DsspDefaultLookup

Drop:

DsspDefaultDrop

Get:

Get

Replace:

Replace

If you run DssInfo and specify RoboticsCommon.dll, you will see several generic contracts and some actual service implementations.

DssProjectMigration: Migrating Services

At this stage, you do not need to migrate any services because all your code is on one computer and you have not upgraded MRDS. However, it is worth mentioning the DssProjectMigration tool so that you can file away it in the back of your mind for later use. This tool can be very useful in a couple of circumstances:

When V2.0 of MRDS arrives, possibly around the time this book is released, you might want to take some of your existing services over to the new version. This is the primary purpose of DssProjectMigration, and it can migrate entire hierarchies of projects. In this case, the new (V2.0) tool will look for known changes to the code and try to fix anything that might break from V1.5.

This tool ensures that a project is set up properly for its current location. If you move a project to a different folder, or if you transfer it to another computer where MRDS is installed on a different disk drive, then you need to update some of the project details. Rather than edit the

.csproj and .sln files yourself, you can let DssProjectMigration take care of it for you.

For more information, you can refer to the online documentation when you need to use

DssProjectMigration.

Deploying Services

Sooner or later, you will want to distribute your services to friends, colleagues, or customers. MRDS includes a tool specifically designed for this purpose: DssDeploy.

There are fundamentally two different ways to deploy a service:

Distribute only the service itself to a computer that already has MRDS installed, i.e., distribute the source code so other people can see it and modify it.

151

www.it-ebooks.info

Part I: Robotics Developer Studio Fundamentals

Distribute the service plus the core components of MRDS so that the packaged service can be run on any computer (assuming the computer is running Windows XP, Vista, Mobile, or CE), i.e., distribute executables only.

For full documentation on DssDeploy, see the online help. This section simply provides two examples illustrating how to use it, but they are two commonly used examples.

Sharing Source Code

If you are interested in sharing your code, you can package it so that other people can install it into their MRDS environment. This is what the authors have done with the ProMRDS code. In this case, the DssDeploy package contains only the source code for the relevant services and the compiled DLLs. All of the object files, debug symbol tables, and so on, are left behind because they can be recreated by compiling the source code.

To build a package for one of the chapters in this book, following these steps:

1. Make a listing of the files from a command prompt using the following:

Dir /b/o:n/s >dir.txt

2.

3.

You can then edit the output file (dir.txt) in Notepad to remove all of the object files and anything else that should not be included. (Strange files sometimes sneak into source directories when you are not looking). The list of files is turned into a DssDeploy options file, which is just a sequence of DssDeploy command-line options. You can use a hash sign (#) to insert comments.

Along with the source files, some other files should be included, such as the DLLs from the bin folder, the ReadMe file, etc. A standard template for an options file helps to ensure that you don’t forget anything. The following example shows the options file for Chapter 2, which is relatively short. Called DeployChapter2Options.txt, it resides in the ProMRDS\Package folder:

#Chapter 2 Deploy Options File

#All Chapter files should follow the same basic format

#Include the deploy options file for later repackaging /d:”..\Package\DeployChapter2Options.txt”

#Chapter Readme.htm and associated files

/d:”..\Chapter2\Readme.htm” /d:”..\Chapter2\images\*” /d:”..\Chapter2\styles\*.css”

#Add the Batch files to run the applications in this chapter #/d:”..\BatchFiles\xxxx.cmd”

#Add the Config files for the applications (if any)

#and the Manifests

152