2016 年 7 月

第 31 卷,第 7 期

本文章是由機器翻譯。

Modern Apps - 使用 UWP 建置 Wi-Fi 掃描器

Frank La La

Wi-fi 優於過去十年左右變成無所不在。許多商店和網路咖啡廳提供方便的客戶免費的 Wi-fi。幾乎所有旅館提供某種類型的無線網際網路都服務與其來賓。大多數人家裡有無線網路。由於一些平板電腦和行動裝置有 Ethernet 插座,Wi-fi 已經成為現代生活的整數。此外,我們很少提供太多的思考。

因此,有很多問題。我們週遭的 Wi-fi 網路的龐大呢? 多少有? 保護它們? 何種通道會在它們是? 它們被具名什麼? 我們可以將它們對應嗎? 我們可以從 Wi-fi 網路的中繼資料來了什麼?

在我的狗最近,我會發生一下我的電話 Wi-fi 網路連線] 畫面,並注意到一些睿智的網路名稱。這讓我不知道多少其他人已選為 comical 與實際的比較。然後,我必須安排和掃描我網路上的芳鄰方面的無線網路的作法。如果我無法自動化程序,我甚至可以掃描,並將無線網路對應運作我通勤期間。在理想情況下,可能會有 Raspberry Pi 會定期掃描以無線方式與記錄資料的 Web 服務上執行的程式。這當然是比看過我的電話或間歇性的實用性。

其實,通用 Windows 平台 (UWP) 提供豐富資料的存取權的無線網路透過 Windows.Devices.WiFi 命名空間中的類別。如您所知,UWP 應用程式可以執行在手機和 Pc 上不僅 Raspberry Pi 2 上執行 Windows 10 IoT 核心。現在,我必須我所需要建置出我的專案。

在本專欄中,我將探討掃描 Wi-fi 網路使用內建於 UWP Api 的基本概念。

Windows.Devices.WiFi 命名空間

Windows.Devices.WiFi 命名空間內的類別可包含掃描,並瀏覽無線介面卡和範圍內的無線網路所需的一切。在 Visual Studio 中建立新的 UWP 專案之後, 加入新的類別稱為 WifiScanner,並新增下列屬性︰

public WiFiAdapter WiFiAdapter { get; private set; }

因為這是可以指定系統上有多個 Wi-fi 介面卡,您必須選擇您想要使用 Wi-fi 配接器。InitializeFirstAdapter 方法會取得第一個在系統中,列舉中所示 [圖 1

[圖 1 尋找第一個 Wi-fi 介面卡連線到系統,並將它初始化

private async Task InitializeFirstAdapter()
{
  var access = await WiFiAdapter.RequestAccessAsync();
  if (access != WiFiAccessStatus.Allowed)
  {
    throw new Exception("WiFiAccessStatus not allowed");
  }
  else
  {
    var wifiAdapterResults =
      await DeviceInformation.FindAllAsync(WiFiAdapter.GetDeviceSelector());
  if (wifiAdapterResults.Count >= 1)
    {
      this.WiFiAdapter =
        await WiFiAdapter.FromIdAsync(wifiAdapterResults[0].Id);
    }
    else
    {
      throw new Exception("WiFi Adapter not found.");
    }
  }
}

新增 Wi-fi 功能

您可能會注意到沒有 Wi-fi 存取檢查,而且如果 RequestAccessAsync 方法會傳回 false 程式碼擲回例外狀況。這是因為應用程式需要的裝置功能,以便讓它掃描並連線到 Wi-fi 網路。這項功能未列在資訊清單的屬性編輯器中的 [功能] 索引標籤。若要加入這項功能,Package.appxmanager 檔案上按一下滑鼠右鍵並選擇 [檢視程式碼。

現在,您會看到 Package.appxmanager 檔案的原始 XML。在 [功能] 節點中,加入下列程式碼︰

<DeviceCapability Name="wifiControl" />

現在,請儲存檔案。您的應用程式現在會有權存取 Wi-fi Api。

瀏覽的無線網路

若要識別 Wi-fi 配接器處理和存取權限的程式碼下, 一步是實際掃描網路。幸運的是,若要這麼做的程式碼是相當簡單。它是只是 WifiAdapter 物件上的 ScanAsync 方法的呼叫。將下列方法加入至 WifiScanner 類別︰

public async Task ScanForNetworks()
{
  if (this.WiFiAdapter != null)
  {
    await this.WiFiAdapter.ScanAsync();
  }
  }

一次 ScanAsync,WifiAdapter NetworkReport 屬性取得填入值。NetworkReport 是 WiFiNetworkReport AvailableNetworks,< WiFiAvailableNetwork > 清單所在的執行個體。WiFiAvailableNework 物件包含有關特定網路的多個資料點。您可以找到服務組識別元 (SSID),訊號強度、 加密方法和存取點執行時間,在其他資料點,完全不需要連線到網路。

逐一查看可用的網路是相當簡單︰ 您可以建立純舊 CLR 物件 (POCO) 包含的某些資料 WiFiAvailableNetwork 物件中,如下列程式碼所示︰

foreach (var availableNetwork in report.AvailableNetworks)
{
  WiFiSignal wifiSignal = new WiFiSignal()
  {
    MacAddress = availableNetwork.Bssid,
    Ssid = availableNetwork.Ssid,
    SignalBars = availableNetwork.SignalBars,
    ChannelCenterFrequencyInKilohertz =
      availableNetwork.ChannelCenterFrequencyInKilohertz,
    NetworkKind = availableNetwork.NetworkKind.ToString(),
    PhysicalKind = availableNetwork.PhyKind.ToString()
  };
}

建置 UI

雖然我想要執行不含 UI 的最後一個專案中的應用程式,它是適用於開發和疑難排解查看範圍和與其相關聯的中繼資料內的網路。它也可用於開發人員可能不具備 Raspberry Pi,但仍想要依照指示進行。中所示 [圖 2, 專案 XAML、 簡單明瞭,而且沒有多行文字方塊來儲存掃描的輸出。

[圖 2 ui 的 XAML

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
  <Grid.RowDefinitions>
    <RowDefinition Height="60"/>
      <RowDefinition Height="60"/>
      <RowDefinition Height="*"/>
  </Grid.RowDefinitions>
  <TextBlock FontSize="36" Grid.RowSpan="2" >WiFi Scanner</TextBlock>
  <StackPanel Name="spButtons" Grid.Row="1" Orientation="Horizontal">
    <Button Name="btnScan" Click="btnScan_Click" Grid.Row="1">Scan For
      Networks</Button>
  </StackPanel>
  <TextBox Name="txbReport" TextWrapping="Wrap" AcceptsReturn="True"
    Grid.Row="2"></TextBox>
  </Grid>
</Page>

擷取位置資料

為了提供附加價值,每個掃描的無線網路也應注意掃描的位置。這將可讓稍後提供有趣的內幕和資料視覺效果。幸運的是,將位置新增至 UWP 應用程式很簡單。不過,必須將位置功能加入您的應用程式。您可以藉由按兩下方案總管] 中的 Package.appxmanifest 檔案,按一下 [功能] 索引標籤中,檢查功能清單中的位置] 核取方塊來這麼做。

下列程式碼將會擷取使用內建於 UWP Api 的位置︰

Geolocator geolocator = new Geolocator();
Geoposition position = await geolocator.GetGeopositionAsync();

有位置之後,您會想要儲存位置的資料。以下是 WiFiPointData 類別,其中儲存位置的資料,以及網路位置中找到的相關資訊︰

public class WiFiPointData
{
  public DateTimeOffset TimeStamp { get; set; }
  public double Latitude { get; set; }
  public double Longitude { get; set; }
  public double Accuracy { get; set; }
  public List<WiFiSignal> WiFiSignals { get; set; }
  public WiFiPointData()
  {
    this.WiFiSignals = new List<WiFiSignal>();
  }
}

在此階段中,是請注意,除非您的裝置有 GPS 裝置,則應用程式需要 Wi-fi 連線到網際網路才能解析位置。您必須有行動作用點,以確保您的膝上型電腦或 Raspberry Pi 2 連線至沒有內建的 GPS 感應器。這也表示報告的位置將會較不精確。如需有關最佳作法的建立位置感知 UWP,請參閱 Windows 開發人員中心文件 」 指導方針的定位感知應用程式,「 在 bit.ly/1P0St0C

掃描重複

掃描和-對應-時-耗案例中,應用程式需要定期掃描 Wi-fi 網路。若要這麼做,您必須使用 DispatchTimer 定期掃描 Wi-fi 網路。如果您不熟悉 DispatchTimer 的運作方式,請參閱文件,網址 bit.ly/1WPMFcp

請務必注意,Wi-fi 掃描最多可能需要幾秒鐘,視您的系統而定。下列程式碼會設定每隔 10 秒,甚至名最慢的系統有足夠時間引發事件的 DispatchTimer:

DispatcherTimer timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 10);
timer.Tick += Timer_Tick;
timer.Start();

每隔 10 秒,計時器會在 Timer_Tick 方法中執行程式碼。下列程式碼掃描 Wi-fi 網路,並再將結果附加至文字方塊中,在 UI 中︰

private async void Timer_Tick(object sender, object e)
{
  StringBuilder networkInfo = await RunWifiScan();
  this.txbReport.Text = this.txbReport.Text + networkInfo.ToString();
}

報表的掃描結果

如前所述,一旦呼叫 ScanAsync 方法,在清單中的 < WiFiAvailableNetwork > 儲存掃描結果。若要取得這些結果它只要是逐一查看清單。中的程式碼 [圖 3 這樣寫的並將結果放入 WiFiPointData 類別的執行個體。

[圖 3 的程式碼來逐一查看在掃描期間找到的所有網路

foreach (var availableNetwork in report.AvailableNetworks)
{
  WiFiSignal wifiSignal = new WiFiSignal()
  {
    MacAddress = availableNetwork.Bssid,
    Ssid = availableNetwork.Ssid,
    SignalBars = availableNetwork.SignalBars,
    NetworkKind = availableNetwork.NetworkKind.ToString(),
    PhysicalKind = availableNetwork.PhyKind.ToString(),
    Encryption = availableNetwork.SecuritySettings.NetworkEncryptionType.ToString()
  };
  wifiPoint.WiFiSignals.Add(wifiSignal);
  }

若要同時又能提供豐富的資料分析的簡單 UI,可以將 WiFiPointData 轉換成逗號分隔值 (CSV) 格式,並在 UI 中設定文字方塊的文字。CSV 是相當簡單的格式,可以匯入 Excel 和 Power BI,供分析。將程式碼轉換 WiFiPointData 示 [圖 4

[圖 4 轉換 WiFiPointData

private StringBuilder CreateCsvReport(WiFiPointData wifiPoint)
{
  StringBuilder networkInfo = new StringBuilder();
  networkInfo.AppendLine("MAC,SSID,SignalBars,Type,Lat,Long,Accuracy,Encryption");
  foreach (var wifiSignal in wifiPoint.WiFiSignals)
  {
    networkInfo.Append($"{wifiSignal.MacAddress},");
    networkInfo.Append($"{wifiSignal.Ssid},");
    networkInfo.Append($"{wifiSignal.SignalBars},");
    networkInfo.Append($"{wifiSignal.NetworkKind},");
    networkInfo.Append($"{wifiPoint.Latitude},");
    networkInfo.Append($"{wifiPoint.Longitude},");
    networkInfo.Append($"{wifiPoint.Accuracy},");
    networkInfo.Append($"{wifiSignal.Encryption}");
    networkInfo.AppendLine();
  }
  return networkInfo;
}

將資料視覺化

當然,我無法等我雲端服務設定為顯示,並將資料視覺化。因此,我花了 CSV 應用程式所產生資料和複製並貼入的文字檔案。我接著會確定儲存檔案。CSV 延伸模組。接下來,我匯入資料到 Power BI Desktop。Power BI Desktop 是從免費下載 powerbi.microsoft.com ,讓您輕鬆地視覺化及探索資料。

若要將資料匯入應用程式中,按一下取得資料 Power Bi Desktop 啟動顯示畫面上。

接下來的畫面,選擇 CSV,然後按一下 [連線。在 [檔案選擇器] 對話方塊中,選擇 CSV 檔案複製並貼上應用程式外的資料。

一旦載入,您會看到欄位的清單在右手邊的畫面上。Power BI Desktop 完整教學課程,說明已超出本文的範圍,而不必花費太多技術來產生視覺效果時,顯示 Wi-fi 網路,其 Ssid 和加密通訊協定的位置就採用中, 所示 [圖 5

Power BI 視覺效果的 Wi-fi 掃描器應用程式資料收集
[圖 5 Power BI 視覺效果的 Wi-fi 掃描器應用程式資料收集

出乎意料地大約三分之一的網路都將完全解密。其中有些是來賓在各種企業設定的網路時,部分並不是。

實際的應用程式

雖然原本的目的只是要測量的技術知識和我的芳鄰的 wit,此專案會有一些相當有趣的實用性。有趣的應用程式能夠輕鬆地自動對應 Wi-fi 訊號強度和位置。可能的縣 (市) 如果? 每個縣 (市) 匯流排所攜帶的 IoT 裝置上執行此應用程式 城市無法測量日益普遍的 Wi-fi 網路,並將該資料與網路上的芳鄰收入資料相互關聯。臨時員工無法再做出明智的原則根據該資料。如果社群提供公用 Wi-fi 城市或在某些方面,訊號強度無法即時傳送周圍的技術人員的成本不為單位。城市也無法判斷所在普遍不安全的網路,並建立目標的認知計劃,以增加社群網路安全性。

規模較小的快速掃描 Wi-fi 網路的中繼資料的功能更為實用之處設定自己的網路時。許多路由器會提供使用者有機會修改他們廣播的通道。絕佳的範例就是稱為 「 Wi-fi 分析器 」 的應用程式 (bit.ly/25ovZ0Q),其中,還會顯示強度和附近的無線網路的頻率。這十分便利的設定中的新位置的 Wi-fi 網路時。

總結

不會縮放複製並貼上從 UI 文字資料。此外,如果目標是要在不顯示任何類型的 IoT 裝置上執行應用程式,則應用程式需要將資料傳送至雲端,不顯示任何 UI。在我下個月的專欄中,您將學習如何設定雲端服務中所有這些資料。此外,您將了解如何將方案部署到執行 Windows IoT 核心 Raspberry Pi 2。


Frank La Vigne 是 Microsoft 技術和民事參與小組的技術推廣者,可協助使用者充分利用技術,以便建立更好的社群。 定期在他的部落格 FranksWorld.com 和已製作成 YouTube 頻道呼叫的 Frank 世界電視 (youtube.com/FranksWorldTV)。

衷心感謝以下技術專家對本文的審閱: Rachel Appel、 Robert 伯和 Jose Luis 方式