GraveDollの備忘録ブログ

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

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 structure (Windows)

プロファイルを作成する

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

私は今回以下のように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 (Windows)

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

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

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

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

やっと接続処理ですが、WlanConnectを使います。
WlanConnect function (Windows)

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

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

注意点

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


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

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

依頼の内容

予算

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の方はまだ試していませんが、こちらはボタンを押さずに改札にタッチすれば反応するよう、デフォルトで設定されているようです。

平成28年度(2016年)秋期ネットワークスペシャリストを受験しました

昨年、ネットワークスペシャリストに落ちたというエントリを書きました。
gravedoll.hatenablog.com

今年もネスペ受けてきましたので午後問題の再現解答を書こうと思います。
今回一週間ほど間が空いてしまったのでちょっと記憶が曖昧な部分もありますが・・・。
昨年より勉強時間がなり少なかったのですが、なんとか時間内に回答欄を全部埋めることができました。
ちなみに午前Ⅰは免除で、午前ⅡはIPAの回答例で自己採点したら合格でした。

午後Ⅰ

問1

設問1

ア:MX
イ:MSV3
ウ:MSV1
エ:SMTPS

設問2

(1)A社のドメインを偽装した迷惑メールが送信される。
(2)ルータ4
(3)
オ:TCP
カ:any
キ:25
(4)セキュアポート
(5)25, 587

設問3

(1)trace route
(2)送信元ドメインIPアドレス

問2

設問1

ア:AES
イ:PSK
ウ:SIM
エ:プロファイル
オ:NAPT
カ:接続

設問2

(1)端末のサイトサーベイによるSSID検出を防ぐ。
(2)電波を不正に取得されるとパケットが解析されるから。
(3)E

設問3

(1)紛失した利用者IDを認証しない。
(2)SW2に接続された機器との通信。

設問4

(1)リバースプロキシ
(2)利用者IDを取得できるようにする。
(3)アクセス時刻, IPアドレス

午後Ⅱ

問1

設問1

(1)
ア:ip1/29
イ:10.0.9.0/24
ウ:ポート番号
(2)32768
(3)追加WEBサーバのIPアドレス設定, FWのフィルタリング定義の更新

設問2

(1)IPアドレスを貸与するISPが異なる。
(2)行きと戻りのIPアドレス空間が異なると通信できなくなるから。

設問3

(1)Bindingレスポンスに格納されているIPアドレスが自分のIPと違うかで判定する。
(2)g2, p
(3)L2SW9, L2SW9
(4)
エ:AP
オ:STUNサーバ

設問4

(1)
カ:HTTP
キ:RTP
(2)一方のUAにはISP1、他方にはISP2のIPアドレスを割り当てる
(3)vlan1, vlan2
(4)
ク:IP-PBX
ケ:名前解決
コ:LB

設問5

(1)
サ:原因の特定
(2)
FQDN:1
グローバルIPアドレス:2
(3)WEBサーバ, STUNサーバ, IP-PBX
(4)LB
(5)マルチホーミングのインターネットアクセス
ブラウザを使ったAP間のビデオ電話
社外のAPから社内のIP電話機への通信
(6)ISP1とISP2で同じゾーンファイルが参照されるか。
(7)①, ①' ③④

教材

今回の試験のために読んだ本はこちら。

極選分析 ネットワークスペシャリスト 予想問題集 (予想問題集シリーズ)

極選分析 ネットワークスペシャリスト 予想問題集 (予想問題集シリーズ)

予想問題集とありますが、トレーニング問題+過去問という構成です。
トレーニング問題は基礎的な技術のしくみが理解できるようになっていて(過去問より難易度は低い)、良問です。
過去問を本格的にやる前におすすめの参考書です。
私は昨年、過去問を結構やっていたのですが、知識の整理のためにこちらを選択しました。
また、午前Ⅱの頻出問題もまとめられていて、数少ない午前Ⅱ対策本にもなっています。
試験前日に午前Ⅱの部分を読んだのですが、試験本番では進研ゼミのマンガように同じ問題が出て、これ一冊で十分でした。

ネスペ本も発売されたらすぐ買ったのですが、読む時間がありませんでした・・・。

ネスペ 27 礎 -ネットワークスペシャリストの最も詳しい過去問解説 (情報処理技術者試験)

ネスペ 27 礎 -ネットワークスペシャリストの最も詳しい過去問解説 (情報処理技術者試験)

Let's note S9 をSSDに換装してみた

私のメインPCはiMacなのですが、サブPCとして学生時代に買ったLet's note S9 CF-S9JYEADRを使っています。

Letsnote CF-S9シリーズ

Letsnote CF-S9シリーズ

たまにしか使わないのですが、最近は起動がかなり遅く、HDDランプがよく付きっぱなしになっていました。
2010年春モデルのため、もう6年前の機種のなので流石に買い換えようかと思っていたのですが、
少し調べてみると同じ機種を持っている方でSSDに換装すると快適になったという記事があり、私もやってみることにしました。
ちなみに今回の記事に書いてる内容はメーカーのサポート外となってしまう行為なので何かあっても自己責任となります( ´Д`)
また、Let's note S9 CF-S9JYEADRはWindows10のサポート外ですが私は勝手にアップグレードしていますw

準備したもの

  • まず肝心のSSDですが、結構迷いました。検討したのはこのあたり。

Transcend SSD 480GB 2.5インチ SATA3 6Gb/s TLC採用 3年保証 TS480GSSD220S

Transcend SSD 480GB 2.5インチ SATA3 6Gb/s TLC採用 3年保証 TS480GSSD220S

  • 結局購入したのはインテルのこちらのものにしました。今のHDD容量(250GB)より少し多く、値段はちょっと高いです。

  • SATA-USBケーブルも買いました。SSDとPCを接続して、古いHDDの内容をそのままコピーするときに使います。

  • そしスペーサーも忘れず購入。SSDはHDDより薄いため、その隙間を埋めるのに使います。

  • 当たり前ですがドライバーも必要ですのでない場合は購入します。私は古いHDDを廃棄するため分解するときに星形が必要だったのでドライバーを新しく購入しました。プラスマイナスもあるしこれ一式で大抵の作業は事足ります。



2万弱かかりましたが同じコストで新しいの買い換えるよりはコスパいい・・・はずw

古いHDDのデータをSSDにコピーする

古いHDDとSSDを交換する前に、古いHDDのクローン(データを丸ごとコピー)をSSDに作成します。
まず、SATA-USBケーブルでSSDとPCを接続したら、PCにSSDを認識させるためにディスクの初期化をおこないます。

  • [コントロールパネル]-[システムとセキュリティ]より、「ハードディスクパーティションの作成とフォーマット」を選択します。

f:id:GraveDoll:20160810125035j:plain

  • 初期化はこの内容でOK

f:id:GraveDoll:20160810125343j:plain


SSDの初期化が終わったらデータ移行ソフトを使ってHDDのデータをSSDにコピーします。
今回はインテル製のSSDなのでインテル公式のソフトを使いました。
downloadcenter.intel.com

  • まずはインストール。インテル製のHDDやSSDが接続されている必要があります。

f:id:GraveDoll:20160810125950j:plain

  • ユーザー登録は任意なので"Register Later"を選択。

f:id:GraveDoll:20160810173906j:plain

  • 「ディスクのクローン作製」を選択。

f:id:GraveDoll:20160810170928j:plain

  • クローンモードは自動を選択。

f:id:GraveDoll:20160810170544j:plain

  • クローン適用後のディスクの状態を確認したら、実行します。

f:id:GraveDoll:20160810170844j:plain


これで放置していればディスクのクローンが作成されます。今回は2時間ほどかかりました。
一応再起動してちゃんとクローンが作成されているか確認してみたほうがいいと思います(PCにはSSDがローカルディスクとして認識されているのでエクスプローラから確認できるはずです)。

SSDの換装

ついにSSDの換装ですが、こちらのサイトが詳しく書かれているので参考にさせていただきました。
というわけで詳細はこちらをご覧くださいw
zigsow.jp
30分もあればできると思います。
換装が完了したらいつものように電源を入れれば以前と同じ状態でPCが起動するはずです。

ついでにメモリの増設

公式では最大4GB(デフォルト2GB+増設用スロットに2GB)なのですが、バッファローによると6GBまで動作を確認してるみたいです。
[http://buffalo.jp/search/pcnew/index.php?id=71021&category=2&type=4&form_name=taiou&action_index_detail=true:title]

というわけで4GBのこちらを購入し、以前増設した2GBのメモリと交換しました。ちなみにデフォルトの2GBメモリはPCを分解しないと交換ができません。

BUFFALO ノートPC用増設メモリ PC3-10600(DDR3-1333) 4GB D3N1333-4G/E

BUFFALO ノートPC用増設メモリ PC3-10600(DDR3-1333) 4GB D3N1333-4G/E

結果

起動(ログイン画面が出るまで)が約2分30秒から約10秒になりました。また、HDDランプが付きっぱなしでモタモタすることもなくなりました。
ベンチンチマークソフト"CrystalDiskMark"による速度測定結果を見てもその差は歴然です。

  • 換装前

f:id:GraveDoll:20160810173325j:plain

  • 換装後

f:id:GraveDoll:20160810173553j:plain


SSDの性能は素晴らしいですね。今回の換装でかなり動作が軽くなり、快適になりました。
買い換えようと思っていたノートPCですが、これでもうしばらく使えそうです。

.Net Framework 4.xでDebug Viewを使ってデバッグ出力を確認する

Windowsアプリを開発してデバッグする際、開発環境のない他のコンピュータ上でプログラムを実行してデバッグ出力を確認したい時があると思います。
C++ではOutputDebugString、C#ではSystem.Diagnostics.Debug.WriteLineやSystem.Diagnostics.Trace.WriteLineなどを使うことでVisual Studio上でデバッグ出力を確認できます。
しかし、とりあえず処理が想定通り行われているか確認したいだけのとき、いちいちVisual Studioをインストールするのも面倒です。
また、人のコンピュータを借りてテストするときなど、何らかの理由でVisual Studioを入れることができない状況もあるのではないでしょうかw
そんなときに役立つのがDebug Viewです。
technet.microsoft.com

Debug View(インストール不要)を実行しておけば、Visual Studioなどの開発環境がなくても実行中のWindowsプログラムのデバッグ出力を確認できます。
しかしC#で.Net Framework4.x環境の場合、そのままではDebug Viewでデバッグ出力を確認できません。
そんなときはDebug Viewの[Capture] - [Capture Global Win32]にチェックを入れ、C#のプログラムに

System.Diagnostics.Debug.Flush();//System.Diagnostics.Debug.WriteLineを使う場合

または

System.Diagnostics.Trace.Flush();//System.Diagnostics.Trace.WriteLineを使う場合

を記述します。
例えば、

System.Diagnostics.Debug.Flush()
System.Diagnostics.Debug.WriteLine("Hello!");
System.Diagnostics.Debug.WriteLine("This is a debug message.");

という感じに記述すればDebug Viewでデバッグ出力を確認できます。