熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

用.Net的Web服務實現天氣預報

2013-11-13 10:23:25  來源: .NET編程 

  該例子演示了利用微軟Net框架的Web服務與天氣預報站點的硬件進行數據交換來實現Web天氣預報的服務

  微軟力推Net的目的用他自己的話來說就是使人們能夠在任何時候任何地點以及任何設備上通過我們開發的軟件發揮最大的潛能在這裡大多數人可能認為微軟所講的任何設備是指袖珍PC手持設備台式電腦及筆記本電腦等下面的例子我們將向大家展示Net如何使那些電腦硬件設備驅動程序開發人員發揮自己的潛能這些設備驅動程序可能和一些專用的PC控制器或PC的標准端口直接通訊這些驅動程序開發人員大多依靠Windows的驅動開發工具包(DDK)及其其他各種工具如可安裝文件系統開發工具包(IFS)等雖然這些微軟的工具包並沒有隨著Net的推出而改變但是Net構架仍然給這些硬件設備開發帶來了新的機遇
 
  我們將要構造的示例方案的目的就是通過專用的PC卡自動采集來自於不同天氣情報采集點的天氣信息PC卡可以通過每個采集點的標識ID來同時控制每個采集點的數據按要求每個采集點可以提供該點的溫度濕度和氣壓等數據
 
  我們的目標是讓用戶通過互聯網(Web)獲得指定采集點的天氣預報信息接下來我們開始結構設計首先需要為PC卡寫一個Windows的驅動程序以便PC卡可以讀取指定采集點的天氣信息另外我們還需要利用Net構造一個網絡服務(Web Service)以便互聯網用戶可以通過Internet訪問采集到的天氣信息數據

  Net的托管代碼是不能直接訪問Windows的內核的所有我們必須先利用非托管代碼寫一個用戶級(User level)的模塊以便網絡服務和PC卡的驅動程序之間可以相互交流數據

  PC卡的驅動程序接口

  假設我們PC采集卡已安裝到專用PC上而且采集點到PC采集開的信號電纜也連接好接下來的任務就是驅動程序開發人員開始開發硬件驅動程序

  我們並不打算深入研究如何開發PC卡的硬件驅動程序其實網上有很多介紹開發驅動程序的工具和資源也有一些介紹在NT和XP下開發驅動程序差異的文章我們的主要目的是關心采集數據的封裝形式以及用戶模塊和驅動程序通訊的方法

  我們准備有下面定義的結構來封裝采集到的數據

  typedef struct {

  unsigned long stationID;

  unsigned long state; // for management purposes

  unsigned long timeStamp;

  double temperature; // celcius

  double humidity; // percent
  
  double airPressure; // millibar

  } WEATHER_DATA *PWEATHER_DATA;

  從PC卡讀取數據我們可以利用Win API DeviceIOControl()為了調用該函數設備驅動程序和用戶程序必須共享用戶定義的IOCTL碼為了簡單起見我們用WEATHER_DATA結構表示用戶程序和驅動程序共享的數據緩沖區但是在實際應用中應該小心謹慎您可以參考微軟的技術文章Q和Q

  用戶要求得到指定的采集點的天氣信息的過程如下

  用戶程序分配WEATHER_DATA結構設置 stationID 和 dataTag

  用戶程序利用Win API CreateFile()打開與PC卡相關聯的設備句柄

  用戶程序調用DeviceIOControl()並將結構 WEATHER_DATA 作為參數

  驅動程序處理調用利用用戶選擇的數據采集點的數據填充WEATHER_DATA數據緩沖區(在我們的例子中用虛擬數據以模仿顯示中的數據采集)

  驅動程序返回數據個用戶程序結束DeviceIOControl()調用
  
  用戶程序處理得到的數據

  以下的頭定義文件為驅動程序和用戶程序共用

  // weather_commonh

  // Common definitions used by both user level module and

  // kernel driver

  //

  #define WEATHER_TYPE

  // The IOCTL function codes from x to xFFF

  // are for customer use

  #define IOCTL_GET_WEATHER_DATA

  CTL_CODE( WEATHER_TYPE x METHOD_BUFFERED FILE_READ_ACCESS | FILE_WRITE_ACCESS)

  // Define common used weather data structure

  typedef struct {

  unsigned long stationID;

  unsigned long state;

  unsigned long timeStamp;

  double temperature;

  double humidity;
 
  double airPressure;

  } WEATHER_DATA *PWEATHER_DATA;

  接下來的代碼是用戶端的實現

  // UserLevelModulecpp

  //

  // Implementation of user level module

  
  
  DWORD dwBytesReturned;

  // Create structure and fill initial data

  WEATHER_DATA dataStruct;

  // specify station to request

  dataStructstationID = stationID;

  

  // Open driver

  HANDLE hDriver;

  hDriver = CreateFile(\\\Device\WeatherDevice);

  
  
  // Issue control call to driver passing prepared structure

  DeviceIOControl(hDriverIOCTL_WEATHER_DATA

  (void*)&dataStructsizeof(dataStruct)

  (void*)&dataStructsizeof(dataStruct)

  &dwBytesReturnedNULL);

  // If succeeded the structure now contains

  // the requested data in data

  

  // Close driver

  CloseHandle(hDriver);

  接下來是驅動程序的部分代碼

  // WeatherDrvc

  //

  // Implementation of kernel driver

  NTSTATUS

  WeatherDispatch(

  IN PDEVICE_OBJECT DeviceObject

  IN PIRP Irp
  
  )

  {

  

  pIrpStack = IoGetCurrentIrpStackLocation(pIrp);

  // Dispatch based on major fcn code

  switch (pIrpStack>MajorFunction)
  
  {

  

  case IRP_MJ_DEVICE_CONTROL:

  // Dispatch on IOCTL

  switch (pIrpStack>ParametersDeviceIoControl

  IoControlCode)

  {

  case IOCTL_GET_WEATHER_DATA:

  pWeatherData = (PWEATHER_DATA)

  pIrp>AssociatedIrpSystemBuffer;

  if(pWeatherData != NULL)

  {

  // Fill time stamp in data structure

  KeQuerySystemTime(&sysTime);

  RtlTimeToTimeFields(&sysTime&tFields);

  pWeatherData>timeStamp = tFieldsSecond

  + * tFieldsMinute

  + * tFieldsHour;

  // Emulate controller card work with

  // sample data

  pWeatherData>temperature = ;

  pWeatherData>humidity = ;

  pWeatherData>airPressure = ;

  }

  pIrp>IoStatusInformation =
  
  sizeof(WEATHER_DATA);

  break;

  default:

  break;

  }
 
  Status = STATUS_SUCCESS;

  break;

  
  
  // Complete request

  }

  用戶端代碼

  驅動程序以及驅動程序和用戶程序的通訊協議定義好了以後接下來就是開發用戶端模塊了

  我們可以開發一個應用程序或者動態連接庫在這裡我們實現一個動態連接庫以下代碼演示了如何輸出一個函數供外部調用

  // weatherDrvCtrlh

  //

  // Declaration of GetWeatherData()

  DWORD WINAPI GetWeatherData(WEATHER_DATA* pData);

  // weatherDrvCtrlcpp

  //

  // Definition of GetWeatherData()

  DWORD WINAPI GetWeatherData(

  WEATHER_DATA* pData)

  {

  HANDLE hDriver;

  DWORD dwErr = ERROR_SUCCESS;

  DWORD dwBytesReturned;

  // Open driver

  HANDLE hDriver;

  hDriver = CreateFile(DRIVER_DEVICE_NAME);

  if(hDriver != INVALID_HANDLE_VALUE)

  {

  // Issue control call to driver

  // passing prepared structure

  dwErr = DeviceIOControl(hDriverIOCTL_WEATHER_DATA

  (void*)&dataStructsizeof(dataStruct)

  (void*)&dataStructsizeof(dataStruct)

  &dwBytesReturnedNULL);

  if(!dwErr)

  {

  // If succeeded the structure now contains
  
  // requested data in data field

  }

  // Close driver

  CloseHandle(hDriver);

  }

  else

  {

  // Handle device open error;

  }

  return dwErr;

  }

  附件的weatherDrvCtrl項目是用Visual Studio Net構造的我們還提供了一個Win的應用程序以供你測試應用程序(weatherDrvCtrl)和驅動程序(weatherDrv)

  到現在為止我們已經完成了驅動程序和用戶端調用的所有工作任何用戶程序都可以通過調用動態庫輸出函數得到指定采集點的天氣信息數據

  網絡服務Web Service

  下面我們來實現Net的網絡服務以便互聯網用戶可以享受我們的服務利用Visual Studio Net創建Web Service很簡單

  啟動Visuao Studio Net;

  新健一個新項目選擇 C# ASP Net Web服務

  編寫數據結構

  [ StructLayout( LayoutKindSequential )]

  public struct WeatherData

  {

  public UInt stationID;

  public UInt state;

  public UInt timeStamp;

  public Double temperature;

  public Double humidity;

  public Double airPressure;

  }

  利用屬性DllImport綁定動態庫weatherDrvCtrlDLL

  [DllImport(weatherDrvCtrldll)]

  static extern unsafe uint GetWeatherData

  (ref WeatherData data);

  創建一個Web方法

  [WebMethod(Description=Get weather data and station state from specified weather station)]

  public unsafe WeatherData

  QueryWeatherData(uint stationID)

  {

  // Create and initialize data structure

  WeatherData weatherData = new WeatherData();

  weatherDatastationID = stationID;

  // Call user level wrapper for device driver

  uint dwRet = GetWeatherData(ref weatherData);

  // If call failed hqndle error here

  return weatherData;

  }

  生成並測試

  如果您按照上述過程正確操作應該得到結果這是一個重要的裡程碑因為你已經創建了一個完整的Web服務您可以注冊您的服務讓更多的人使用它(具體的注冊Web服務請參考)(代碼實驗室)


From:http://tw.wingwit.com/Article/program/net/201311/13454.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.