Gururi.log

id:Gururiの記録です。

iPhoneのBluetoothテザリングで自動接続

きっかけ

ひとりぶろぐ » MacBookに3G/LTE通信機能が搭載されたらいいのにな。そんな願いにアプローチするLidSyncPAN
iPhone5のテザリングは便利である。俺も常時Lightningケーブルを2本、ポケットに持ち歩いているが、やはりiPhoneを取り出し、ケーブルを繋ぎ、iPhoneが落っこちない場所を確保して、と結構面倒くさい。そんな中、上記の記事が流れて来た。確かはてブのホットエントリーだった気がするが、まあどうでもいい。俺的な問題点は

  • 蓋の開け閉めだけかぁ……
  • EasySIMBLが必要?あんまり入れたくないなあ……

この2点。よろしい、ならば自分で書くしかあるまい。

仕様

  • 基本的にAppleScriptで制御すること。
  • 特殊なユーティリティの使用禁止。Mavericksの基本機能だけで使えること。
  • より優先される他のネットワーク接続(たとえばWiFiによる接続)が検出されたらテザリング切断。
  • より優先される他のネットワーク接続が無くなったらテザリング開始

スクリプト

普通にポインタを操作して接続・接続解除を行う場合、

  1. メニューバーのBluetoothアイコンをクリック
  2. 接続したいiPhoneの名前をクリック
  3. 「ネットワークへ接続」または「ネットワークから接続解除」をクリック

という流れになる。てことはSystem Eventsだな。大前提として、メニューバーにはBluetoothが表示されているものとするのでその辺のエラー処理は省略。

まずは接続・接続解除のためのAppleScript

このスクリプトはコンパイルして適当な場所(~/Documents/AppleScript/TetheringController.scptとか)に放り込んでおく。

property iPhone : "Gururi's iPhone" --実際にメニューに表示される自分のiPhoneの名前を入れておくこと

on tethering(flag)
	if (flag) then
		set {select_menu, notifymessage, notifytitle} to {"ネットワークへ接続", "Bluetoothテザリングを開始しました", "テザリングを開始しました。"}
	else
		set {select_menu, notifymessage, notifytitle} to {"ネットワークから接続解除", "別の接続を認識したのでテザリングを停止しました", "テザリングを停止しました。"}
	end if
	tell application "System Events"
		tell application process "SystemUIServer"
			try
				tell menu bar 1
					set bt to item 1 of (menu bar items whose description is "bluetooth")
				end tell
				tell bt
					click it
					click menu item iPhone of menu 1
					click menu item select_menu of menu 1 of menu item iPhone of menu 1
				end tell
				display notification (notifymessage) with title notifytitle
			on error errMsg number errNum
				click bt
			end try
		end tell
	end tell
	return flag
end tethering

on tetheringon()
	return my tethering(true)
end tetheringon

on tetheringoff()
	return my tethering(false)
end tetheringoff
次に用意するのはシェルスクリプト

色々悩んだんだけど、networksetupの-getinfoサブコマンドでIP addressを取得できるかどうかで、そのnetworkserviceが接続されているかどうかを判断することにしてみた。とりあえず俺の環境ではメインがWi-FiでテザリングがBluetooth PANなのでこんな感じになってますが、必要に応じて該当する部分を変更・追加すれば使えるんじゃないかなー、と思います。サービス名とか、if文とか。

#!/bin/zsh
while [ 0 ]
do
PAN=`networksetup -getinfo "Bluetooth PAN" |grep '^IP address:' |wc -l`
WIFI=`networksetup -getinfo Wi-Fi |grep '^IP address:' |wc -l`
#-getinfoのあとの"Bluetooth PAN"やWi-Fiは、「ネットワーク」システム環境設定でのサービス名。
#サービス名が空白を含む場合は""で全体を囲むか、空白をエスケープすること。
if [ $WIFI -eq 0 ];then
	#$WIFIが0→Wi-FiでIPアドレス無し
	if [ $PAN -eq 0 ];then
		#$PANが0→Bluetooth PANにIPアドレス無し
		osascript -e 'tetheringon() of (load script alias (((home directory of (system info)) as string) & "Documents:AppleScript:TetheringController.scpt"))'
		#~/Documents/AppleScript/TetheringController.scptを読み込んでtetheringon()を実行
	fi
else
	#$WIFIが0でない→Wi-FiでIPアドレスあり
	if [ $PAN -eq 1 ];then
		#$PANが0でない→Bluetooth PANにIPアドレスあり
		osascript -e 'tetheringoff() of (load script alias (((home directory of (system info)) as string) & "Documents:AppleScript:TetheringController.scpt"))'
		#Wi-Fiの接続を使用するのでPANの接続は切る。
		#~/Documents/AppleScript/TetheringController.scptを読み込んでtetheringoff()を実行
	fi
fi
sleep 10
#次のループに行く前に10秒待ちます。この時間はお好みで。
done

こいつは/usr/local/bin/TetheringControllerにインストールして、

% sudo chown root:staff /usr/local/bin/TetheringController
% sudo chmod 755 /usr/local/bin/TetheringController

しておきます。

ほいでもってlaunchd用のplistファイル

TetheringControllerを呼び出して起動してくれるようにするための設定ファイルです。今回は自分だけで使うので、保存場所は~/Library/LaunchDaemons/com.gururi.tetheringcontroller.plistです。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>KeepAlive</key>
	<true/>
	<key>Label</key>
	<string>com.gururi.tetheringcontroller</string>
	<key>OnDemand</key>
	<false/>
	<key>ProgramArguments</key>
	<array>
		<string>/usr/local/bin/TetheringController</string>
	</array>
	<key>RunAtLoad</key>
	<true/>
</dict>
</plist>
監視のオンオフAppleScript

次で最後。こいつは~/Library/Scripts/に放り込んでおいて、スクリプトメニューバーに表示し、実行する度に監視の開始・停止を相互に切り替える。ファイル名、俺は「トグルテザリング監視」にしてる。まあファイル名は自分が分かればいいのでお好きにどうぞ。

on run
	do shell script "launchctl list|grep tetheringcontroller|wc -l"
	if (result as integer) = 0 then
		do shell script "launchctl load -w ~/Library/LaunchDaemons/com.gururi.tetheringcontroller.plist"
		display notification "テザリングの監視を開始しました" with title "テザリング監視開始"
	else
		do shell script "launchctl unload -w ~/Library/LaunchDaemons/com.gururi.tetheringcontroller.plist"
		display notification "テザリングの監視を停止しました" with title "テザリング監視停止"
	end if
end run

以上を適切な場所にインストールした上で、監視のAppleScriptを実行すればよろし。一度監視を開始すれば、ログアウト/再起動後も監視は継続されます。

インストーラパッケージ

基本的に俺が使うために作った物を「使う物好きもいるかもなー」的な考えで公開しているだけなので、そんなものは無い(・ω・)

追記

LidSyncPANと同様、初回起動時に「システム環境設定>セキュリティとプライバシー>プライバシー>アクセシビリティ」からTetheringControllerに対して制御の許可を与えてやる必要があります。