415 lines
23 KiB
HTML
415 lines
23 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" >
|
|
<head>
|
|
<title>PnP-X Simple Thermostat Sample</title>
|
|
<style type="text/css">
|
|
.style1
|
|
{
|
|
font-family: Calibri;
|
|
}
|
|
.style2
|
|
{
|
|
font-family: Calibri;
|
|
font-style: italic;
|
|
margin-left: 40px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<p>
|
|
<span style="font-size: 18pt; color: #0000cc; font-family: Calibri"><strong>
|
|
PnP-X Simple Thermostat Sample</strong></span></p>
|
|
<p>
|
|
<span style="font-family: Calibri">
|
|
Last Updated: February 2009</span></p>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
<span style="font-size: 14pt; color: #0000cc; font-family: Calibri"><strong>
|
|
Demonstrates</strong></span></p>
|
|
<p>
|
|
<span style="font-family: Calibri">
|
|
This sample demonstrates an end-to-end scenario using PnP-X. It includes device
|
|
samples using UPnP and WSD, a driver to install the devices in PnP, proxies to talk
|
|
with the devices, and a client application that uses the devices through the proxies. Developers will find this sample useful when implementing
|
|
end-to-end scenarios using PnP-X or just implementing a small portions of a scenario,
|
|
like a PnP-X compliant device.</span></p>
|
|
<p>
|
|
<span style="font-family: Calibri">
|
|
This sample uses the following technologies: PnP-X, Function Discovery (FD), Web
|
|
Services on Devices (WSD), Universal Plug and Play
|
|
(UPnP), and Windows Plug and Play (PnP).</span></p>
|
|
<p>
|
|
<span style="font-family: Calibri">
|
|
The following diagram shows how all the parts of the scenario fit together from
|
|
a process perspective. The brown colored components are the components this sample contains and the blue colored components are built into Windows (Vista and later). The names of brown components
|
|
directly correspond to the Visual Studio projects in the sample. The numbers on the arrows correspond to the steps involved
|
|
in running the scenario (see 'Running the Sample' further down in this document).</span></p>
|
|
<p class="style1">
|
|
<i><b>Windows 7 Notes:</b></i></p>
|
|
<p class="style2">
|
|
The new way to pair a device in Windows 7 is via Devices and Printers' Add a
|
|
device wizard instead of the Network folder. <b>Start Menu</b> -> <b>
|
|
Devices and Printers</b> -> <b>Add a device</b>. For this sample, when you
|
|
see the Network folder referred to, you can replace that with the 'Add a device'
|
|
wizard. Further, PnP-X devices will be shown (and can be managed) from
|
|
Devices and Printers after they have been paired and installed.</p>
|
|
<p>
|
|
<span style="font-family: Calibri"></span> </p>
|
|
<p>
|
|
<img src="scenario.jpg" alt="Scenario Diagram" style="font-family: Calibri; font-size: 12pt; color: #000000;"/><span
|
|
style="font-family: Calibri"> </span></p>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
<span style="font-size: 14pt; color: #0000cc; font-family: Calibri"><strong>
|
|
Prerequisites</strong></span></p>
|
|
<ul>
|
|
<li><span style="font-family: Calibri">This sample requires Windows Vista or later to run.</span></li>
|
|
<li class="style1">Visual Studio 2008 is needed to edit the Solution and Projects.</li>
|
|
<li class="style1">Sample supports x86 and x64.</li>
|
|
</ul>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
<span style="font-size: 14pt; color: #0000cc; font-family: Calibri"><strong>
|
|
Languages</strong></span></p>
|
|
<p>
|
|
<span style="font-family: Calibri">C++</span></p>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
<span style="font-size: 14pt; color: #0000cc; font-family: Calibri"><strong>
|
|
Folders and Files</strong></span></p>
|
|
<ol style="list-style-position: outside; list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>\ </strong></span></li>
|
|
<li>
|
|
<ol style="list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>readme.htm </strong>- This file. </span>
|
|
</li>
|
|
<li><span style="font-family: Calibri"><strong>scenario.jpg</strong> - Diagram showing the scenario layout from a process
|
|
perspective. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostat.sln</strong> - Visual Studio
|
|
2008 solution file. This solution
|
|
file encapsulates all the projects for this sample. Each folder under the root defines
|
|
a project and contains a Visual Studio project file. </span></li>
|
|
</ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri"><strong></strong></span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostatClient\ </strong></span>
|
|
</li>
|
|
<li>
|
|
<ol style="list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>main.cpp</strong> - Implements a client
|
|
application that uses ISimpleThermostat devices. </span></li>
|
|
</ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri"><strong></strong></span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostatDriver\ </strong></span>
|
|
</li>
|
|
<li>
|
|
<ol style="list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostat.inf </strong>- INF file used when installing the sample devices. </span></li>
|
|
</ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri"><strong></strong></span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostatInterface\ </strong>
|
|
</span></li>
|
|
<li>
|
|
<ol style="list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostat.idl</strong> - Defines ISimpleThermostat. ISimpleThermostat is the interface this sample revolves
|
|
around: from devices supporting ISimpleThermostat functionality to the client that
|
|
uses ISimpleThermostat. </span></li></ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri"><strong></strong></span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostatProxy\ </strong></span>
|
|
</li>
|
|
<li>
|
|
<ol style="list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>common.h</strong> - Common header used
|
|
by all source files in this project. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>CSimpleThermostatProviderFactory.h</strong>
|
|
- Defines the CSimpleThermostatProviderFactory class. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>CSimpleThermostatServiceProvider.h</strong>
|
|
- Defines the CSimpleThermostatServiceProvider class. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>CSimpleThermostatProviderFactory.cpp</strong>
|
|
- Implements the CSimpleThermostatProviderFactory class which is used to create
|
|
CSimpleThermostatServiceProvider objects. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>CSimpleThermostatServiceProvider.cpp</strong>
|
|
- Implements the CSimpleThermostatServiceProvider class which is used by FD to create
|
|
the device proxies. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>dllmain.cpp</strong> - Standard functions
|
|
needed to implement and register the dll. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>helpers.cpp</strong> - Helper functions used by CSimpleThermostatServiceProvider. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostatProxy.def</strong>
|
|
- Defines the exports for the dll. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostatProxy.idl</strong>
|
|
- Defines the type library and CoClass for
|
|
the SimpleThermostatProxy. </span></li>
|
|
</ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri"><strong></strong></span></li>
|
|
<li><span style="font-family: Calibri"><strong>UPnP\UPnPSimpleThermostatDevice\ </strong>
|
|
</span></li>
|
|
<li>
|
|
<ol style="list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>main.cpp</strong> - Implements control
|
|
code for the UPnP device. </span></li>
|
|
</ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri"><strong></strong></span></li>
|
|
<li><span style="font-family: Calibri"><strong>UPnP\UPnPSimpleThermostatDeviceDLL\
|
|
</strong></span></li>
|
|
<li>
|
|
<ol style="list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>common.h</strong> - Common header used
|
|
by all the source files in this project. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>CSimpleThermostatDevice.h</strong>
|
|
- Defines the CSimpleThermostatDevice class. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>CSimpleThermostatDeviceFactory.h</strong>
|
|
- Defines the CSimpleThermostatDeviceFactory class. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>CSimpleThermostatService.h</strong>
|
|
- Defines the CSimpleThermostatService class. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>CSimpleThermostatDevice.cpp</strong>
|
|
- Implements the CSimpleThermostatDevice
|
|
class which is the core UPnP device class. This is the object that will be registered
|
|
with the UPnPHost. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>CSimpleThermostatDeviceFactory.cpp</strong>
|
|
- Implements the CSimpleThermostatDeviceFactory class which is used to create CSimpleThermostatDevice
|
|
objects. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>CSimpleThermostatService.cpp</strong>
|
|
- Implements the CSimpleThermostatService class which is the service for the UPnP
|
|
device. This service contains the ISimpleThermostat functionality. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>dllmain.cpp</strong> - Standard functions
|
|
needed to implement and register the dll. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostatDevice.def </strong>
|
|
- Defines the exports for the dll. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostatDevice.idl</strong>
|
|
- Defines the type library, coclass, and
|
|
service interface for the UPnP device.
|
|
</span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostatDevice.xml </strong>
|
|
- Description document for the UPnP device. Defines the metadata for the device.
|
|
</span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostatService.xml </strong>
|
|
- Description document for the UPnP service. Defines the metadata for the service.
|
|
</span></li>
|
|
</ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri"></span></li>
|
|
<li><span style="font-family: Calibri"><strong>UPnP\UPnPSimpleThermostatProxy\ </strong>
|
|
</span></li>
|
|
<li>
|
|
<ol style="list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>CUPnPSimpleThermostatProxy.h </strong>
|
|
- Defines the CUPnPSimpleThermostatProxy class. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>CUPnPSimpleThermostatProxy.cpp</strong>
|
|
- Implements the CUPnPSimpleThermostatProxy
|
|
class which is used by client applications to communicate with the device's service.
|
|
This class exposes ISimpleThermostat to the client, which then knows how to talk with
|
|
the device using protocol specific commands.
|
|
</span></li>
|
|
</ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri"></span></li>
|
|
<li><span style="font-family: Calibri"><strong>WSD\WSDSimpleThermostatContract\ </strong>
|
|
</span></li>
|
|
<li>
|
|
<ol style="list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>codegen.config </strong>- WsdCodeGen
|
|
configuration file. This file essentially
|
|
describes everything about the WSD device.
|
|
WsdCodeGen can consume this file to
|
|
auto generate C++ code that implements the device. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostat.wsdl</strong> - WSDL file used by WsdCodeGen to create a
|
|
template codegen.config file. </span></li>
|
|
</ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri"></span></li>
|
|
<li><span style="font-family: Calibri"><strong>WSD\WSDSimpleThermostatDevice\ </strong>
|
|
</span>
|
|
<ol style="list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>CSimpleThermostatService.h</strong>
|
|
- Defines the CSimpleThermostatService class. </span><span style="font-family: Calibri"> </span></li>
|
|
<li><span style="font-family: Calibri"><strong>CSimpleThermostatService.cpp</strong>
|
|
- Implements the CSimpleThermostatService class which is the service for the WSD
|
|
device. This service contains the ISimpleThermostat functionality. </span></li>
|
|
<li><span style="font-family: Calibri"><strong>main.cpp</strong> - Implements the
|
|
control code for the WSD device.</span></li></ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri"></span></li>
|
|
<li><span style="font-family: Calibri"><strong>WSD\WSDSimpleThermostatGenerated\ </strong>
|
|
</span>
|
|
<ol style="list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostat_WSDProxy.h</strong>
|
|
- GENERATED by WsdCodeGen. Defines the CSimpleThermostat_WSDProxy class.</span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostat_WSDTypes.h</strong>
|
|
- GENERATED by WsdCodeGen. Defines all the custom types used by the device, proxy,
|
|
and stub.</span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostat_WSD.idl</strong> -
|
|
GENERATED by WsdCodeGen. Defines the WSD protocol specific version of the
|
|
ISimpleThermostat interface: ISimpleThermostat_WSD.</span></li><li><span style="font-family: Calibri"><strong>SimpleThermostat_WSDProxy.cpp</strong>
|
|
- <span style="font-family: Calibri">GENERATED by WsdCodeGen. Implements
|
|
the CSimpleThermostat_WSDProxy class, which is used by the CWSDSimpleThermostatProxy
|
|
class. </span> </span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostat_WSDStub.cpp</strong>
|
|
- GENERATED by WsdCodeGen. Implements the stub code for the device's service.
|
|
</span></li>
|
|
<li><span style="font-family: Calibri"><strong>SimpleThermostat_WSDTypes.cpp</strong>
|
|
- GENERATED by WsdCodeGen. Implements the custom types used by the device, proxy, and stub. </span></li>
|
|
</ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri"><strong></strong></span></li>
|
|
<li><span style="font-family: Calibri"><strong>WSD\WSDSimpleThermostatProxy\ </strong>
|
|
</span>
|
|
<ol style="list-style-type: none;">
|
|
<li><span style="font-family: Calibri"><strong>CWSDSimpleThermostatProxy.h</strong>
|
|
- Defines the CWSDSimpleThermostatProxy class.</span></li><li><span style="font-family: Calibri"><strong>CWSDSimpleThermostatProxy.cpp</strong>
|
|
- Implements the CWSDSimpleThermostatProxy class which is used by the client application
|
|
to communicate with the device's service. This class exposes ISimpleThermostat to
|
|
the client, which then knows how to talk with the device using protocol specific commands.
|
|
</span></li>
|
|
</ol>
|
|
</li>
|
|
</ol>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
<span style="font-size: 14pt; color: #0000cc; font-family: Calibri"><strong>
|
|
Building the Sample (using Visual Studio)</strong></span></p>
|
|
<ol>
|
|
<li><span style="font-family: Calibri">Open SimpleThermostat.sln in Visual Studio.
|
|
</span></li>
|
|
<li><span style="font-family: Calibri">In the Build menu, select <strong>Build Solution</strong>.
|
|
The application will be built in the
|
|
default \Debug or \Release directory. </span></li>
|
|
</ol>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
<span style="font-size: 14pt; color: #0000cc; font-family: Calibri"><strong>
|
|
Building the Sample (from SDK build environment)</strong></span></p>
|
|
<ol>
|
|
<li><span style="font-family: Calibri">Open the SDK command shell. </span></li>
|
|
<li><span style="font-family: Calibri">Navigate to the sample folder where SimpleThermostat.sln is located. </span></li>
|
|
<li><span style="font-family: Calibri">Type <strong>vcbuild SimpleThermostat.sln</strong>.
|
|
The application will be built in the default
|
|
\Debug or \Release directory. </span></li>
|
|
</ol>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
<span style="font-size: 14pt; color: #0000cc; font-family: Calibri"><strong>
|
|
Running the Sample</strong></span></p>
|
|
<p>
|
|
<span style="font-family: Calibri">
|
|
All files can be used from the binplaced location from the build (typically \debug
|
|
or \release). Note that the driver package is built to support both x86 and x64,
|
|
so you'll find the driver package in a folder called "DriverPackage".</span></p>
|
|
<p>
|
|
<span style="font-family: Calibri">
|
|
The step numbers here directly correspond to the arrow labels on the scenario diagram
|
|
above. As you run the sample you can look at the scenario diagram to better understand
|
|
what's happening.</span></p>
|
|
<ol>
|
|
<li><span class="style1">Pre-install the Simple Thermostat Driver package.</span><ol style="list-style-type: lower-alpha;">
|
|
<li><span style="font-family: Calibri">From the \DriverPackage folder run <strong>pnputil -a SimpleThermostat.inf
|
|
</strong>.</span></li>
|
|
<li><span style="font-family: Calibri">A Windows Security dialog will pop-up because
|
|
the driver is not signed. Click <strong>Install this driver software anyway</strong>.
|
|
</span></li>
|
|
<li><span style="font-family: Calibri">After several seconds the driver installation will complete, resulting in SimpleThermostatProxy.dll being copied to <windir>\system32 and being registered as a COM object.<br /> </span></li>
|
|
</ol>
|
|
</li>
|
|
<li><span class="style1">Start the simple thermostat devices. You can run one or both of the UPnP and WSD
|
|
devices. </span>
|
|
<ol style="list-style-type: lower-alpha;">
|
|
<li><span style="font-family: Calibri">Run <b>WSDSimpleThermostatDevice.exe</strong></b>.</span></li><li><span style="font-family: Calibri">Run <strong>regsvr32 UPnPSimpleThermostatDevice.dll</strong>
|
|
(you must have administrative rights to do this).</span></li><li><span style="font-family: Calibri">Run <strong>UPnPSimpleThermostatDevice.exe</strong>.
|
|
<em>Note: If this returns a FILE_NOT_FOUND
|
|
error (0x80070002) then UPnPHost most likely does not have rights to access the device's
|
|
description documents. To fix this you need to change permissions on the folder
|
|
where the description documents are located.
|
|
From Windows Explorer, right click the folder and click <strong>Properties</strong>.
|
|
Click the <strong>Security</strong> tab and click <strong>Edit.</strong> Click <strong>
|
|
Add</strong> and in the
|
|
text box type "<strong>LOCAL SERVICE</strong>". Click
|
|
<strong>OK </strong>on all three dialog boxes and
|
|
rerun the device.</em><br />
|
|
</span>
|
|
</li>
|
|
</ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri">Install the devices from the Network folder.
|
|
</span>
|
|
<ol style="list-style-type: lower-alpha;">
|
|
<li><span style="font-family: Calibri">Open the Network folder by clicking <strong>
|
|
Start Menu </strong>-> <strong>Network</strong>.
|
|
</span></li>
|
|
<li><span style="font-family: Calibri"> After a few seconds you should see the two devices listed in the Network
|
|
folder. One is named 'UPnP Simple Thermostat' and the other 'WSD Simple Thermostat'. </span></li>
|
|
<li><span style="font-family: Calibri">If for some reason you are unable to see the devices in the list after a short
|
|
period, have the devices start again. You can perform this by pressing the 'p' key
|
|
and then the 's' key for each device. </span>
|
|
</li>
|
|
<li><span style="font-family: Calibri">Install each device by double clicking it,
|
|
or by selecting it and clicking install
|
|
from the command bar. Windows will ask for your permission to install the device.<br />
|
|
</span>
|
|
</li>
|
|
</ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri">The IPBusEnum service communicates with the device to get the metadata needed for installation in PnP.
|
|
<br />
|
|
</span>
|
|
</li>
|
|
<li><span style="font-family: Calibri">The IPBusEnum service installs the device in PnP after several seconds.<br />
|
|
</span>
|
|
</li>
|
|
<li><span style="font-family: Calibri">Find installed ISimpleThermostat devices using
|
|
the client application. </span>
|
|
<ol style="list-style-type: lower-alpha;">
|
|
<li><span style="font-family: Calibri">Run <strong>SimpleThermostatClient.exe</strong>.</span></li><li><span style="font-family: Calibri">The client asks FD for all the ISimpleThermostat devices in PnP. It should list
|
|
the two devices you just installed. Select the one you want to use.<br />
|
|
</span>
|
|
</li>
|
|
</ol>
|
|
</li>
|
|
<li><span style="font-family: Calibri">Use ISimpleThermostat devices using the client application. </span>
|
|
<ol style="list-style-type: lower-alpha;">
|
|
<li><span style="font-family: Calibri">After selecting one of the devices the client will attempt to call some of the
|
|
ISimpleThermostat functions on the device using the SimpleThermostatProxy.dll.</span></li><li><span style="font-family: Calibri">The client will display the name, ID, current temperature setting, and desired
|
|
temperature of the thermostat device. It will also display a small list of options
|
|
you can choose from. </span></li>
|
|
<li><span style="font-family: Calibri">From the menu you can refresh device info, make a call to the device to set the
|
|
desired temperature, or exit the client. </span>
|
|
</li>
|
|
</ol>
|
|
</li>
|
|
</ol>
|
|
<p>
|
|
</p>
|
|
<p>
|
|
<span style="font-size: 14pt; color: #0000cc; font-family: Calibri"><strong>
|
|
Removing the Sample</strong></span></p>
|
|
<ol>
|
|
<li><span style="font-family: Calibri">Before shutting down the devices, select them in the Network folder and click <strong>Uninstall </strong>from the command bar. </span></li>
|
|
<li><span style="font-family: Calibri">Run <strong>regsvr32 -u UPnPSimpleThermostatDevice.dll</strong>.
|
|
</span></li>
|
|
<li><span style="font-family: Calibri">From <windir>\system32 run <strong>regsvr32
|
|
-u SimpleThermostatProxy.dll</strong>.</span></li><li><span style="font-family: Calibri">Find the oemXX.inf file in <windir>\inf that corresponds to SimpleThermostat.inf.
|
|
The INF file will contain the comment
|
|
description "INF for WSD and SSDP ISimpleThermostat devices". </span></li>
|
|
<li><span style="font-family: Calibri">Run <strong>pnputil -f -d [oemxx.inf file from above]</strong>. You do not need the path to the
|
|
.inf file. (Example: pnputil -f
|
|
-d oem99.inf). </span>
|
|
</li>
|
|
<li><span style="font-family: Calibri">Delete <windir>\system32\SimpleThermostatProxy.dll.
|
|
</span></li>
|
|
</ol>
|
|
<p>
|
|
</p>
|
|
|
|
</body>
|
|
</html>
|