自宅iBeaconの改良
今回は小ネタですが、以前「REBL600FRで自宅iBeacon」で書いた、自宅iBeaconの改良記事です。当初の自宅iBeaconは外出(exit region)・帰宅(enter region)で「いってらっしゃい」「おかえりなさい」のメッセージを投げるだけでした。今回、帰宅時にWiFiがOFFの場合は、ONにするよう通知する機能を追加しました。
2014/10/3追記:iOS 8への対応を追記しました。
機能追加の目的
私はau iPhone5を使っているのですが、通勤路線の駅毎にau WiFiを掴んでくれます。一時期掴まなくなっていたのですが、最近なぜか復活しました。多くの方が感じていると思いますが、これ、ハッキリ言って『迷惑』です。たいがい品質の悪いWiFiを掴み停車中はLTEに比べてアクセス速度がスローダウン、電車が動き出してもしばらくWiFiを離してくれない(モバイル/LTEに切り替えてくれない)ためアクセスが止まってしまいます。そのため、電車に乗っている間は通常WiFiをOFFにしています。
家に帰ったときWiFiをONにし忘れていると、そういうときに限って、子供がモバイル/LTEの状態でYou Tubeを使い倒してパケットカウントを上げてくれることがあります・・・まあ、7Gの上限に到達することはないのですが、家にいるときはWiFiを使った方が速度も速いし、キャリアにも優しいので、家ではWiFiをONにするのを忘れないようにしたいものです。
そこで、iBeaconと連動して、家に帰ったときにWiFiがOFFの場合は、ONにするよう通知を出すようにしました。通知のイメージはこんな感じです。
下から2行目の「おかえりなさい」時はWiFiがONなのでそのまま、上から2行目の「おかえりなさい」時はWiFiがOFFのため、「WiFiをOnにしましょう」と追加メッセージを投げています。
実現方式
最初は、iOSでWiFiのOn/Off状態を取得するAPIがないか調べてみたのですがなさそうです。On/Offの設定をするのは当然、脱獄(Jail Break)しないと無理とstackOverflowにも書いてあります。iOSの場合、インタフェースの状態を調べるAPIはなさそうなので、他の方法として、Reachabilityクラスを使うことにしました(使い方は、このサイトを参考にしました)。
Reachabilityクラスは、iOSでネット接続の状態を調べることができるクラスで、WiFi接続状態、モバイル(3G/4G)接続状態、未接続状態などを取得できます。間接的な方法ですが、家に帰ったとき(iBeacon regionに入ったとき)Reachability状態がモバイル接続の場合、WiFiがOFFであると判定します。
コード
コードを以下に示します。
// // ViewController.m // Bea子v2 // // Created by Todotani on 2014/05/11. // #import "ViewController.h" #import "Reachability.h" @interface ViewController () @property (strong, nonatomic) CLLocationManager *locationManager; @property (strong, nonatomic) NSUUID *proximityUUID; @property (strong, nonatomic) CLBeaconRegion *beaconRegion; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; if ([CLLocationManager isMonitoringAvailableForClass:[CLCircularRegion class]]) { self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; self.proximityUUID = [[NSUUID alloc] initWithUUIDString:@"03BA6107-9F0A-4461-B1D8-504DA65632DD"]; self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID: self.proximityUUID identifier:@"com.todotani.ibeacon"]; [self.locationManager startMonitoringForRegion: self.beaconRegion]; } else { //iBeaconが利用できないOS, Deviceの場合 NSLog(@"お使いの端末ではiBeaconを利用できません。"); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"確認" message:@"お使いの端末ではiBeaconを利用できません。" delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK", nil]; [alert show]; } } // 指定した領域に入った場合 - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { [self sendLocalNotificationForMessage:@"おかえりなさい、ご主人様"]; [NSThread sleepForTimeInterval:5.0]; Reachability *reachablity = [Reachability reachabilityForInternetConnection]; NetworkStatus status = [reachablity currentReachabilityStatus]; if (status == ReachableViaWWAN) { [self sendLocalNotificationForMessage:@"WiFiをOnにしましょう"]; } } // 指定した領域から出た場合 - (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region { [self sendLocalNotificationForMessage:@"いってらっしゃい、ご主人様"]; } #pragma mark - Private methods - (void)sendLocalNotificationForMessage:(NSString *)message { UILocalNotification *localNotification = [UILocalNotification new]; localNotification.alertBody = message; localNotification.fireDate = [NSDate date]; localNotification.soundName = UILocalNotificationDefaultSoundName; [[UIApplication sharedApplication] scheduleLocalNotification:localNotification]; } @end
50行目に5秒のsleepが入れてあるのは、家に帰った際に自宅WiFiに接続される前に53行目の条件判定が動いて、WiFi ONの場合でもOFFと誤判定するのを回避するためです。5秒のsleepを入れることで、WiFiがONの場合は確実に接続されてから条件判定を行います。sleepを入れるのは、汚いコードで気に入らないのですが、仕方なく妥協。
iOS 8への対応
2014/10/3追記:iPhoen 6の発売早々に機種変してしまいました(キャリアも訳あってドコモにチェンジ)。iPhone 6設定後「Be子 App」を再度入れても動いてくれません。iOS 8から位置情報取得設定(iBeaconを使う場合は位置情報取得をOnにする必要があります)の方法が変わっていますが、設定 → プライバシー → 位置情報サービスから「Be子 App」の位置情報取得を「常に許可」にしても勝手に「許可しない」に戻されてしまい、iBeaconが検知できません。Twitterで症状を流したら、@tw_hoehoeさんから、リンクのblogに記載がある問題であることを教えてもらいました。このblogによると、常時位置情報取得を許可するためにはinfo.plistを編集して、”NSLocationAlwaysUsageDescription”エントリを作り、”This app use iBeacon Loacation”などの適当なString Valueを設定する必要があります。
iOS 8になって、設定条件が変わった箇所に当たってしまったということでした。
我が家のiBeaconたち
当初は、ランニングエレクトロニクスさんのREBL600FR 1個で運用していましたが、部屋を移動するとiBeaconが切れ、「いってらっしゃいませ」「おかえりなさい」を繰り返すフラップ状態になることがあったため、現在はスイッチサイエンスさんのmbed HRM1017との2台体制にしています。BL600FRは電池駆動を生かして、電源が取れない居間の壁に貼り付けてあり、HRM1017はパソコン部屋においてACアダプタから電源を取っています。
Friskケースに入れて壁に貼り付けたREBL600FR
机の上に置いた、mbed HRM1017
最近のコメント