GraveDollの備忘録ブログ

勉強したことや捗るグッズの備忘録です。

光回線をexcite光からMEC光に変更してみた

私の家は光回線をexcite光(フレッツ光とexciteの光コラボ)で契約していました。
普通にWEBサイトを見るだけなら問題なかったのですが、動画など大容量のファイルをダウンロードするとかなり遅い(特に夜中)のでイライラしていました。
プロバイダを変更しようかと思っていたところ、exciteがMEC光というサービスを提供しているのを知りました。
IPv6/IPoEという混雑していない通信方式のため、スピードが出るらしいです。

問題の背景と技術的な詳細はこちらの記事が詳しいです。
blog.amedama.jp

料金

私はファミリータイプの契約となっているので、以下の料金です。
マンションタイプはもっと安いです。

excite光:基本料金4360 + ホームゲートウェイのレンタル200円
MEC光:基本料金4500 + ルータのレンタル300円

ということで利用料金は少しだけ高くなりました。
DS-Lite機能がないとダメだからなのか、ルータのレンタルは必須となっています。

準備

excite光を契約していたので、特に立ち入り工事等はありませんでした。
電話もなかったです。
ルータと書類が送られて、既存のルータをリプレースするだけで完了です。

スピードテスト

  • excite光

f:id:GraveDoll:20180506215736p:plain

  • MEC光

f:id:GraveDoll:20180506215740p:plain


DownloadとPINGを見ていただければわかるのですが、格段に早くなっています。
実際動画のダウンロードもすぐに終わって快適になりました。

GitHub Shopで買い物してみた

あまりGitHubで活動できていないのですが、なんとなくGitHub Shop見てたら無性に欲しくなってきて買い物しました。

github.myshopify.com

注文は簡単

海外のショップなので住所の書き方とか色々調べないとな・・・と思ってたのですが、やってみると日本の通販サイトと同じ感覚で買い物できました。
住所は郵便番号を入れれば市町村まで自動入力されますし、もちろんクレジットカード(JCBは使えませんがw)も使えます。
注文が完了した後は配送状況の確認もできます。

注文詳細

買ったものは以下の通り。Octocatのフィギュアも買おうと思っていたのですが売り切れていました。前日見たときはまだ注文できる状態だったので、タッチの差ですかね(;´Д`)
送料(Shipping)はやっぱり高いですね。可能ならば共同購入をおすすめしますw

1x Invertocat Hoodie - Small for $55.00 each
1x GitHub Drip Tee - Linear/Men’s / Small / Black for $25.00 each
1x Octocat Stickers - 10 Pack (3") for $2.00 each
1x Cork Coasters for $5.00 each
1x Invertocat 2.0 Shirt - Linear/Men’s / Small for $25.00 each

Subtotal : $112.00 USD
Shipping : $38.21 USD
Total : $150.21 USD

注文から届くまで

3/21に注文して、予定通り3/27に届きました。大体一週間くらいでしょうか。

注意

私の場合発送されてから配送業者のフェデックスからメールが来て、商品単価がわかる書類などあれば送ってほしいと連絡がありました。
通関で必要だったのでしょうか?注文時にGitHub Shopから届いた注文確認メールを添付して返信しました。

ついに到着!

他の方の記事を読んでいると楽しげなパッケージで届くと想像していたのですが、シンプルな白いパッケージでした。汚れが長旅を物語っていましたがw
開封済みシールが貼ってあったので、やはり税関で引っかかったみたいです。

こちらが中身。

  • 左下のInvertocat 2.0 Shirtはよく見ないとプリントがわからないです。あと、丈が長いです。
  • 左上のGitHub Drip Teeはロゴがアメリカンでかっこいいですね。こっちも丈がちょっと長いかな〜。
  • 真ん中のInvertocat Hoodieは小柄な私にはSサイズでちょうどよかったです。
  • コースターは4枚もあるので会社と家で使おうと思います。
  • ステッカーは10枚入りですがまだどこに貼るか考えていませんw

f:id:GraveDoll:20180328003347j:plain


・・・という感じで簡単に買い物できました。
Tシャツの丈は長かったですが、海外のお土産Tシャツっぽくてこれはこれでアリかなと思いますw
一応サイズチャートがあるので確認しておくと良いと思います(インチ表記なのでわかりづらいですが)。American Apparel など、どのメーカー製かは各商品説明に記載があります。
github.myshopify.com

グッズを揃えたし、今年はもっとGitHubに草を生やしていきたいところです。

Wi-Fi QRコードを作成してアクセスポイントに接続してみた

iOS11の新機能として、標準のカメラアプリでQRコードを読み取ることでアクセスポイントに接続できます。
ということで、実際に自分でQRコードを作成してアクセスポイント(自宅のルータ)に接続してみました。
QRコードならSSID教えたりパスワードの入力だったりがいらないので、家に来たお客さんがWi-Fiに使いたいってときにサッと接続できていいかもしれないですね。
ちなみに、AndroidでもQRコード読み取りアプリがWi-Fi接続対応していれば可能です。

Wi-FI接続用の文字列フォーマットについて

調べてみると以下の記事に詳しく書かれていました。
news.mynavi.jp

Wi-Fiに接続するためのフォーマットは以下のように決められているようです。

WIFI:S:(SSID);T:(暗号化方式);P:(パスフレーズ);;

(SSID)を接続したいアクセスポイントのSSID、(暗号化方式)を接続したいアクセスポイントの暗号化方式、(パスフレーズ)を接続したいアクセスポイントのパスフレーズに置き換えてください。

例えば、SSIDが"MyWi-Fi", 暗号化方式がWPA2-PSK, パスフレーズが"PassPhrase"の場合は

WIFI:S:MyWi-Fi;T:WPA;P:PassPhrase;;

となります。最後は;(セミコロン)が2つなので注意して下さい。

QRコードの作成

あとはこのテキストをQRコードにするだけです。
qr.quel.jp
上記QRコード作成サイトなどで、先程のフォーマットに従ったテキストをQRコードに変換しましょう。

アクセスポイントに接続

iPhoneの標準カメラアプリを開き、先程作成したQRコードを写してください。
アクセスポイントへの接続を確認する通知が現れるはずです。
f:id:GraveDoll:20180114000332p:plain
タップすることで接続されます。簡単!

パスフレーズは丸見え状態

作成してみればわかりますが、ただのテキストをQRコードにしているだけです。
当然テキストの読み取りとしてQRコードを読み取れば、QRコードに埋め込まれたパスフレーズは丸見えなので注意してください。

Native Wifiを使ってみた その2

前回、Native Wifiを使って利用可能なネットワークのスキャンをおこないました。
gravedoll.hatenablog.com


今回は無線アクセスポイントに接続する処理を実装してみたいと思います。
サンプルコードはこちら。無線アクセスポイントのSSIDとセキュリティキーを入力し、接続するようになっています。
github.com


以下、接続までの処理についてのメモです。

接続時のパラメータを設定する

//接続パラメータ設定
ZeroMemory(&wlanConnectionParams, sizeof(WLAN_CONNECTION_PARAMETERS));
wlanConnectionParams.wlanConnectionMode = wlan_connection_mode_profile;//接続形式の指定(今回は接続する際にプロファイルを使う形式を指定)
wlanConnectionParams.strProfile = ssid;//接続するプロファイル名を指定(今回はSSID名を指定)
wlanConnectionParams.pDot11Ssid = &dot11Ssid;//接続するAPのSSIDを指定
wlanConnectionParams.pDesiredBssidList = NULL;//BSSリストの指定(今回は使用しない)
wlanConnectionParams.dot11BssType = dot11_BSS_type_infrastructure;//BSSタイプの指定(普通にAPに接続するならインフラストラクチャを指定する)
wlanConnectionParams.dwFlags = 0;//フラグの指定(ステルスのネットワーク接続するかどうかなどが指定できる)

今回は無線アクセスポイントに接続するために、SSID、セキュリティキー、暗号化方式などが含まれるプロファイルを作成・保存し、そのプロファイルをもとに接続をおこなうようパラメータを指定しています。
wlanConnectionModeをwlan_connection_mode_temporary_profileにすればプロファイルを保存せずに接続ができるっぽいのですが、私はうまくできませんでした(;´Д`)

WLAN_CONNECTION_PARAMETERSのドキュメントはこちらです。
_WLAN_CONNECTION_PARAMETERS | Microsoft Docs

プロファイルを作成する

プロファイルはXML形式で作成します。
暗号化方式別のサンプルが用意されているので、こちらを参考にプロファイルを作成します。
Wireless Profile Samples | Microsoft Docs

私は今回以下のようにXMLをベタ打ちしていますw

wchar_t strXml[1024];
LPCWSTR key = securityKey;
wchar_t profileFormat[] = L"<?xml version=\"1.0\" encoding=\"US-ASCII\"?>"
	L"<WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\">\n"
	L"<name>%s</name>\n"
	L"<SSIDConfig>\n"
	L"<SSID>\n"
	L"<name>%s</name>\n"
	L"</SSID>\n"
	L"</SSIDConfig>\n"
	L"<connectionType>ESS</connectionType>\n"
	L"<connectionMode>auto</connectionMode>\n"
	L"<autoSwitch>false</autoSwitch>\n"
	L"<MSM>\n"
	L"<security>\n"
	L"<authEncryption>\n"
	L"<authentication>WPA2PSK</authentication>\n"
	L"<encryption>AES</encryption>\n"
	L"<useOneX>false</useOneX>\n"
	L"</authEncryption>\n"
	L"<sharedKey>\n"
	L"<keyType>passPhrase</keyType>\n"
	L"<protected>false</protected>\n"
	L"<keyMaterial>%s</keyMaterial>\n"
	L"</sharedKey>\n"
	L"</security>\n"
	L"</MSM>\n"
	L"</WLANProfile>\n";
_snwprintf_s(strXml, _countof(strXml), profileFormat, ssid, ssid, key);

プロファイルを登録する

WlanSetProfileで先ほど作成したプロファイルを登録します。

WlanSetProfile function | Microsoft Docs

WlanSetProfile(hClient, guid, 0, strXml, 0, true, NULL, &dwReasonCode);

という感じで、第四引数にプロファイルを指定しています。

ここで登録されたプロファイルは、Windows10の場合、[ネットワーク設定] - [既知のネットワークの管理]で確認できると思います。
Windows7は[ネットワークと共有センター] - [ワイヤレスネットワークの管理]で確認できます。

無線アクセスポイントに接続する

やっと接続処理ですが、WlanConnectを使います。
WlanConnect function | Microsoft Docs

WlanConnect(hClient, guid, &wlanConnectionParams, NULL);

第三引数で最初に設定した接続パラメータを指定しています。

注意点

WlanConnectがエラーを返さなかったとしても接続が成功したとは限りません。
信頼性を高めるためにはIPが当たっているかを確認したり、通知を見て接続エラー判定したりといった処理が別途必要だと思います。


日経ITエンジニアスクール 無線LAN構築 最強の指南書

日経ITエンジニアスクール 無線LAN構築 最強の指南書

知人の結婚式のプロフィールムービーを作ってみた

昨年の話になりますが、知人に結婚式で流すプロフィールムービーの作成を頼まれたので、そのときのメモ。

依頼の内容

予算

20000円を制作費として頂きました。アニメーション素材の購入でほぼ使い切りました。

構成

新郎の生い立ち→新婦の生い立ち→二人の思い出→両親へのメッセージ
という内容です。曲は新郎のパートで1曲(最初のサビまで)、残りのパートで1曲(フル)で頼まれました。

納品形式

DVD

環境

PC:iMac
動画作成ソフト:iMovie, After Effects
DVDライティングソフト:Toast DVD

ムービー作成

スライドショー

スライドショー(写真に曲とテロップを付けて流すだけ)ならiMovieで十分でした。
iMovieは初めて使ったのですが、直感的に操作ができるので誰でも簡単に動画作成ができます。

アニメーション

スライドショーだけだと少し物足りないので、動画のオープニングとエンディングとして短いアニメーションを入れることにしました。
アニメーションはAdobeAfter Effectsを使ってみることにしました。
www.adobe.com
体験版が一週間あるので一気に作ってしまうのもありですね。
また、Adobe製品は高いイメージがあったのですが、お手頃価格で必要な期間だけ使用できるプランがあったので気軽に購入できました。
creative.adobe.com

アニメーションの素材はvideohiveで購入しました。"Wedding titles"などで検索するとたくさん素材が出てくると思います。
videohive.net

購入の仕方はこちらが詳しいです。
Videohiveの使い方 - 自作映像の作り方・裏ワザテンプレート集

After Effectsはプロの方が使うソフトなのでiMovieより操作が難しいですが、videohiveの素材には編集方法も大抵同梱されているので、
最低限の編集はできるかと思います。私は文字の変更、可視状態の変更とタイムラインのカットアンドペーストだけでそれなりのものができました。
動画に出力して、iMovie内でスライドショーとくっつければプロフィールムービーの完成です。


はじめよう!  作りながら楽しく覚える After Effects

はじめよう! 作りながら楽しく覚える After Effects

プロが教える!  After Effects デジタル映像制作講座 CC/CS6対応

プロが教える! After Effects デジタル映像制作講座 CC/CS6対応

DVD作成

Toast DVDを使ってDVDにライティングしました。
「高解像度DVD」を選べばHD画質のDVDが作れますが、その場合AVCHDに対応したブルーレイプレイヤーが必要なので式場に問い合わせてみてください。
itea40.jp

本番環境のテストは必須

必ず式の前に本番環境でテストしてもらいましょう。私はテロップが途切れているシーンがあったので、一度修正しました。

Native Wifiを使ってみた その1

Windows無線LANの設定を行うためのAPIとして、Native WifiMicrosoftより提供されています。
利用可能なネットワーク一覧の取得や、無線アクセスポイントへの接続などがC/C++で実現できます。
Native Wifi (Windows)

Windows無線LANに関するアプリを作ることになたっためこのNative Wifiを使うことにしたのですが、調べてみても言語問わずあまり情報がありません。
しかし、自分なりにいろいろと試行錯誤しているうちに知見が蓄積されてきたのでメモしておきます。

なお、C#の場合、Native WifiをP/InvokeしたAPIがManaged Wifiとして公開されています。すべてを網羅しているわけではなさそうですが・・・。
managedwifi.codeplex.com

サンプル

簡単なサンプルがMicrosoftより公開されています。
無線LANインターフェースの状態取得、利用可能なネットワーク情報の取得がこれらのコードで確認できると思います。
Native Wifi API Sample (Windows)

通知の取得

上記サンプルにある関数WlanGetAvailableNetworkList()では利用可能なネットワーク一覧が取得できますが、これはリアルタイムのものではなくOSが定期的にスキャンした結果のキャッシュを取得しています。
そのため直前に出現したアクセスポイントのネットワークを取得できない可能性があります。
そこでWlanScan()関数を使い、スキャン結果の通知を取得することでリアルタイムで利用可能なネットワークを取得しますが、これには数秒を要します。
そのため、OSからの「通知」を取得することでスキャンの状況に応じた処理を行います。
通知を取得するためには、WlanRegisterNotification()を使います。
WlanRegisterNotification function (Windows)

リアルタイムで利用可能なネットワークを取得するサンプル

というわけでWlanScan()関数を使い、スキャン結果の通知を取得することでリアルタイムで利用可能なネットワークを取得するサンプルを作ってみました。
Microsoftが公開しているサンプルを改変しています。

#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <wlanapi.h>
#include <objbase.h>
#include <wtypes.h>

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <wchar.h>

// Need to link with Wlanapi.lib and Ole32.lib
#pragma comment(lib, "wlanapi.lib")
#pragma comment(lib, "ole32.lib")

static bool bScanWait = true;


//無線に関する通知を行うコールバック関数
static void WlanNotification(WLAN_NOTIFICATION_DATA *wlanNotifData, VOID *p)
{
	//ロケール指定
	setlocale(LC_ALL, "japanese");
	WCHAR strReason[1024];

	//通知元をauto configuration module(ACM)に設定
	if (wlanNotifData->NotificationSource == WLAN_NOTIFICATION_SOURCE_ACM) {
		PWLAN_CONNECTION_NOTIFICATION_DATA pConnNotifData = NULL;
		WCHAR *notificationMessage;

		switch (wlanNotifData->NotificationCode) {
		case wlan_notification_acm_scan_complete: //スキャン完了
			notificationMessage = L"wlan_notification_acm_scan_complete";
			bScanWait = false;
			break;
		case wlan_notification_acm_scan_fail: //スキャン失敗
			notificationMessage = L"wlan_notification_acm_scan_fail";
			pConnNotifData = (PWLAN_CONNECTION_NOTIFICATION_DATA)wlanNotifData->pData;
			if (pConnNotifData->wlanReasonCode != ERROR_SUCCESS) {
				bScanWait = false;
				WlanReasonCodeToString(pConnNotifData->wlanReasonCode, 1024, strReason, NULL);
				wprintf(L"ScanFailed Reason: %ls\n", strReason);
			}
			break;
		case wlan_notification_acm_scan_list_refresh: //ネットワーク一覧が更新された
			notificationMessage = L"wlan_notification_acm_scan_list_refresh";
			break;
		default:
			notificationMessage = L"Unknown:";
			break;
		}

		wprintf(L"%ls\n", notificationMessage);
	}

}

int wmain()
{

	// Declare and initialize variables.

	HANDLE hClient = NULL;
	DWORD dwMaxClient = 2;      //    
	DWORD dwCurVersion = 0;
	DWORD dwResult = 0;
	DWORD dwRetVal = 0;
	int iRet = 0;

	WCHAR GuidString[39] = { 0 };

	unsigned int i, j, k;

	/* variables used for WlanEnumInterfaces  */

	PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
	PWLAN_INTERFACE_INFO pIfInfo = NULL;

	PWLAN_AVAILABLE_NETWORK_LIST pBssList = NULL;
	PWLAN_AVAILABLE_NETWORK pBssEntry = NULL;

	int iRSSI = 0;

	DWORD dwPrevNotif = 0;
	bScanWait = true;

	dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient);
	if (dwResult != ERROR_SUCCESS) {
		wprintf(L"WlanOpenHandle failed with error: %u\n", dwResult);
		return 1;
		// You can use FormatMessage here to find out why the function failed
	}

	dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList);
	if (dwResult != ERROR_SUCCESS) {
		wprintf(L"WlanEnumInterfaces failed with error: %u\n", dwResult);
		return 1;
		// You can use FormatMessage here to find out why the function failed
	}
	else {
		wprintf(L"Num Entries: %lu\n", pIfList->dwNumberOfItems);
		wprintf(L"Current Index: %lu\n", pIfList->dwIndex);
		for (i = 0; i < (int)pIfList->dwNumberOfItems; i++) {
			pIfInfo = (WLAN_INTERFACE_INFO *)&pIfList->InterfaceInfo[i];
			wprintf(L"  Interface Index[%u]:\t %lu\n", i, i);
			iRet = StringFromGUID2(pIfInfo->InterfaceGuid, (LPOLESTR)&GuidString,
				sizeof(GuidString) / sizeof(*GuidString));
			// For c rather than C++ source code, the above line needs to be
			// iRet = StringFromGUID2(&pIfInfo->InterfaceGuid, (LPOLESTR) &GuidString, 
			//     sizeof(GuidString)/sizeof(*GuidString)); 
			if (iRet == 0)
				wprintf(L"StringFromGUID2 failed\n");
			else {
				wprintf(L"  InterfaceGUID[%d]: %ws\n", i, GuidString);
			}
			wprintf(L"  Interface Description[%d]: %ws", i,
				pIfInfo->strInterfaceDescription);
			wprintf(L"\n");
			wprintf(L"  Interface State[%d]:\t ", i);
			switch (pIfInfo->isState) {
			case wlan_interface_state_not_ready:
				wprintf(L"Not ready\n");
				break;
			case wlan_interface_state_connected:
				wprintf(L"Connected\n");
				break;
			case wlan_interface_state_ad_hoc_network_formed:
				wprintf(L"First node in a ad hoc network\n");
				break;
			case wlan_interface_state_disconnecting:
				wprintf(L"Disconnecting\n");
				break;
			case wlan_interface_state_disconnected:
				wprintf(L"Not connected\n");
				break;
			case wlan_interface_state_associating:
				wprintf(L"Attempting to associate with a network\n");
				break;
			case wlan_interface_state_discovering:
				wprintf(L"Auto configuration is discovering settings for the network\n");
				break;
			case wlan_interface_state_authenticating:
				wprintf(L"In process of authenticating\n");
				break;
			default:
				wprintf(L"Unknown state %ld\n", pIfInfo->isState);
				break;
			}
			wprintf(L"\n");

			//コールバックの登録
			dwResult = WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_ACM, FALSE, (WLAN_NOTIFICATION_CALLBACK)WlanNotification, NULL, NULL, &dwPrevNotif);
			if (dwResult != ERROR_SUCCESS) {
				wprintf(L"WlanRegisterNotification failed with error: %u\n", dwResult);
				return 1;
			}

			//利用可能なネットワークをスキャン
			dwResult = WlanScan(hClient, &pIfInfo->InterfaceGuid, NULL, NULL, NULL);
			if (dwResult != ERROR_SUCCESS) {
				wprintf(L"WlanScan failed with error: %u\n", dwResult);
				return 1;
			}

			while (bScanWait) {
				Sleep(100);
			}

			dwResult = WlanGetAvailableNetworkList(hClient,
				&pIfInfo->InterfaceGuid,
				0,
				NULL,
				&pBssList);

			if (dwResult != ERROR_SUCCESS) {
				wprintf(L"WlanGetAvailableNetworkList failed with error: %u\n",
					dwResult);
				dwRetVal = 1;
				// You can use FormatMessage to find out why the function failed
			}
			else {
				wprintf(L"WLAN_AVAILABLE_NETWORK_LIST for this interface\n");

				wprintf(L"  Num Entries: %lu\n\n", pBssList->dwNumberOfItems);

				for (j = 0; j < pBssList->dwNumberOfItems; j++) {
					pBssEntry =
						(WLAN_AVAILABLE_NETWORK *)& pBssList->Network[j];

					wprintf(L"  Profile Name[%u]:  %ws\n", j, pBssEntry->strProfileName);

					wprintf(L"  SSID[%u]:\t\t ", j);
					if (pBssEntry->dot11Ssid.uSSIDLength == 0)
						wprintf(L"\n");
					else {
						for (k = 0; k < pBssEntry->dot11Ssid.uSSIDLength; k++) {
							wprintf(L"%c", (int)pBssEntry->dot11Ssid.ucSSID[k]);
						}
						wprintf(L"\n");
					}

					wprintf(L"  BSS Network type[%u]:\t ", j);
					switch (pBssEntry->dot11BssType) {
					case dot11_BSS_type_infrastructure:
						wprintf(L"Infrastructure (%u)\n", pBssEntry->dot11BssType);
						break;
					case dot11_BSS_type_independent:
						wprintf(L"Infrastructure (%u)\n", pBssEntry->dot11BssType);
						break;
					default:
						wprintf(L"Other (%lu)\n", pBssEntry->dot11BssType);
						break;
					}

					wprintf(L"  Number of BSSIDs[%u]:\t %u\n", j, pBssEntry->uNumberOfBssids);

					wprintf(L"  Connectable[%u]:\t ", j);
					if (pBssEntry->bNetworkConnectable)
						wprintf(L"Yes\n");
					else {
						wprintf(L"No\n");
						wprintf(L"  Not connectable WLAN_REASON_CODE value[%u]:\t %u\n", j,
							pBssEntry->wlanNotConnectableReason);
					}

					wprintf(L"  Number of PHY types supported[%u]:\t %u\n", j, pBssEntry->uNumberOfPhyTypes);

					if (pBssEntry->wlanSignalQuality == 0)
						iRSSI = -100;
					else if (pBssEntry->wlanSignalQuality == 100)
						iRSSI = -50;
					else
						iRSSI = -100 + (pBssEntry->wlanSignalQuality / 2);

					wprintf(L"  Signal Quality[%u]:\t %u (RSSI: %i dBm)\n", j,
						pBssEntry->wlanSignalQuality, iRSSI);

					wprintf(L"  Security Enabled[%u]:\t ", j);
					if (pBssEntry->bSecurityEnabled)
						wprintf(L"Yes\n");
					else
						wprintf(L"No\n");

					wprintf(L"  Default AuthAlgorithm[%u]: ", j);
					switch (pBssEntry->dot11DefaultAuthAlgorithm) {
					case DOT11_AUTH_ALGO_80211_OPEN:
						wprintf(L"802.11 Open (%u)\n", pBssEntry->dot11DefaultAuthAlgorithm);
						break;
					case DOT11_AUTH_ALGO_80211_SHARED_KEY:
						wprintf(L"802.11 Shared (%u)\n", pBssEntry->dot11DefaultAuthAlgorithm);
						break;
					case DOT11_AUTH_ALGO_WPA:
						wprintf(L"WPA (%u)\n", pBssEntry->dot11DefaultAuthAlgorithm);
						break;
					case DOT11_AUTH_ALGO_WPA_PSK:
						wprintf(L"WPA-PSK (%u)\n", pBssEntry->dot11DefaultAuthAlgorithm);
						break;
					case DOT11_AUTH_ALGO_WPA_NONE:
						wprintf(L"WPA-None (%u)\n", pBssEntry->dot11DefaultAuthAlgorithm);
						break;
					case DOT11_AUTH_ALGO_RSNA:
						wprintf(L"RSNA (%u)\n", pBssEntry->dot11DefaultAuthAlgorithm);
						break;
					case DOT11_AUTH_ALGO_RSNA_PSK:
						wprintf(L"RSNA with PSK(%u)\n", pBssEntry->dot11DefaultAuthAlgorithm);
						break;
					default:
						wprintf(L"Other (%lu)\n", pBssEntry->dot11DefaultAuthAlgorithm);
						break;
					}

					wprintf(L"  Default CipherAlgorithm[%u]: ", j);
					switch (pBssEntry->dot11DefaultCipherAlgorithm) {
					case DOT11_CIPHER_ALGO_NONE:
						wprintf(L"None (0x%x)\n", pBssEntry->dot11DefaultCipherAlgorithm);
						break;
					case DOT11_CIPHER_ALGO_WEP40:
						wprintf(L"WEP-40 (0x%x)\n", pBssEntry->dot11DefaultCipherAlgorithm);
						break;
					case DOT11_CIPHER_ALGO_TKIP:
						wprintf(L"TKIP (0x%x)\n", pBssEntry->dot11DefaultCipherAlgorithm);
						break;
					case DOT11_CIPHER_ALGO_CCMP:
						wprintf(L"CCMP (0x%x)\n", pBssEntry->dot11DefaultCipherAlgorithm);
						break;
					case DOT11_CIPHER_ALGO_WEP104:
						wprintf(L"WEP-104 (0x%x)\n", pBssEntry->dot11DefaultCipherAlgorithm);
						break;
					case DOT11_CIPHER_ALGO_WEP:
						wprintf(L"WEP (0x%x)\n", pBssEntry->dot11DefaultCipherAlgorithm);
						break;
					default:
						wprintf(L"Other (0x%x)\n", pBssEntry->dot11DefaultCipherAlgorithm);
						break;
					}

					wprintf(L"  Flags[%u]:\t 0x%x", j, pBssEntry->dwFlags);
					if (pBssEntry->dwFlags) {
						if (pBssEntry->dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED)
							wprintf(L" - Currently connected");
						if (pBssEntry->dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED)
							wprintf(L" - Has profile");
					}
					wprintf(L"\n");

					wprintf(L"\n");
				}
			}
		}

	}

        //通知の解除
	if (hClient != NULL) {
		dwResult = WlanRegisterNotification(hClient, WLAN_NOTIFICATION_SOURCE_NONE, TRUE, NULL, NULL, NULL, &dwPrevNotif);
	}
	if (pBssList != NULL) {
		WlanFreeMemory(pBssList);
		pBssList = NULL;
	}

	if (pIfList != NULL) {
		WlanFreeMemory(pIfList);
		pIfList = NULL;
	}

	return dwRetVal;
}

このサンプルを実行すると、

wlan_notification_acm_scan_complete
wlan_notification_acm_scan_list_refresh

が出力され、さらに無線LANインターフェースと最新の利用可能なネットワーク情報が出力されたはずです。
WlanScan()は結果の取得までに数秒(4秒以内)かかるため、スキャン完了通知を待つ処理を入れています。4秒以内に取得できない場合はタイムアウトするようです。
なお、一度接続済みで、プロファイルが保存されているネットワークが見つかった場合、同じSSIDのネットワークが重複して取得されています(プロファイル情報ありのものと、プロファイル情報無しのもの)。
利用可能なネットワーク一覧結果を表示する場合は、必要に応じてスクリーニングすることになるかと思います。

これでさっき立てたばかりのアクセスポイントも取得できるようになりました。
このように、より信頼性の高いアプリには通知の取得が必須だと思います。

次回はアクセスポイント接続に関するエントリを投稿したいと思います。

Apple Watch Series2でApple payを使ってみた

Apple payが日本でもサービス開始されたましたね。
私も早速使ってみましたのでレポートします。

バイス環境

iPhone6
Apple Watch Series2

Apple PayはiOS 10.1から対応

ということで、最初にiPhoneをアップデートさせました。

iPhoneのWalletアプリにカードを登録

アップデート後に再起動すると、最初にクレジットカードをWalletアプリに登録する画面が出てきました。
メインで使っているリクルートカードプラスを登録しようとしたのですが、残念ながら登録できませんでした・・・。
代わりにクレジットとSuica一体型のViewカード(ルミネカードバージョン)を登録しました。
そして、実物のカードは店舗で使えなくなるという通知が表示されました。
カメラでクレジットカードを撮影すれば番号を認識してくれるので簡単です。こういう機能をサラッと使えるのがiPhoneの良いところですね。
後からいつでもWalletアプリでクレジットカードを追加できます。

Watch OSは3.1から対応

iPhoneと同様、Apple Watchもアップデートさせました。

Apple Watchにカードを登録

iPhone で Watch Appアプリを開いて、Wallet と Apple Payから先程追加したカードを選択して登録します。

私の場合、これでApple WatchによるQUICPayによる支払い(Apple Watchをタッチしていクレカ払い)ができるようになりました。
他にもiD払いがあるのですが、どちらになるかは登録したクレジットカードにより決まるようです。

ViewカードSuicaはWalletアプリに取り込まれない

Suica一体型のクレジットカードであるViewカードですが、カードに付いているSuicaはWalletアプリに取り込まれません。
つまり、クレジットカード機能のみiPhoneApple WatchのWalletアプリに取り込んだことになります。
そのため、Suicaアプリにより新たなSuicaを発行する必要があります。
私はSuicaアプリをダウンロードし、そこからSuica(記名式)を発行しました。
モバイルSuicaに登録することになるのですが、そのとき個人情報を入力するフォームが勝手に動いて凄く入力しづらかったです(;´Д`)
チャージするときに紐付けるクレジットカードはWalletに登録したものから選ぶことができます。

Viewカードに残ったSuicaはどうなるのか?

実物のカードは店舗で使えないようなのですが、Suicaの残高はあります。
クレカとしての機能はなくても、Suicaをチャージしたり支払いしたりはできるのでしょうか・・・?
ちょっと調べてみたのですがわかりませんでした。
このへんの説明がもっとあってもいい気がします。

早速コンビニでQUICPayで支払い

というわけでコンビニでApple WatchによるQUICPay払いをしてきました。
店員にQUICPayで支払うことを告げ、Apple Wachの横についているボタンを二回押すと、登録したカードが表示されます。
スワイプで支払いに使うカードを選んで、レジの端末にタッチし、「クイックペイ!」という効果音が鳴れば支払い完了となります。
Suicaの方はまだ試していませんが、こちらはボタンを押さずに改札にタッチすれば反応するよう、デフォルトで設定されているようです。