Home > 1:Program, iPhone > 設定した場所に到着したらiPhoneにプッシュ通知するプログラム

設定した場所に到着したらiPhoneにプッシュ通知するプログラム

2009年07月09日

MOONGIFTさんで『MobileMeを使ってiPhoneにPHPからメッセージ「Sosumi」』というエントリーがあったのでほほぅ…と思ってたのですが、ちゃんとエントリーを読んでみると「ロケーションに関するデータを得ることもできる」とのこと!

数日まえにtwitterでつぶやいた

iphoneで、あらかじめ設定した場所に着いたらプッシュ通知してくれる仕組み欲しいなぁ
Twitter / Yoshitaka Masuda: iphoneで、あらかじめ設定した場所に着いたらプッ …

っていう事ができるじゃないの!ということで試しに組んでみました。

組んでみたプログラムは、
・あらかじめ設定した場所に到着したら、手元にあるiPhoneに指定したメッセージをプッシュ通知する。
・あらかじめ設定した場所に到着したら、指定したメールアドレスにメッセージを送信する。
というものです。

必要なものは
・iPhone
・MobileMe
・定期的にPHPをつつける環境
といったところ。iPhoneがOS 3.0でiPhoneを探す機能がONになっている必要があります。

■注意
今回作ったプログラムは「こんなことも出来るんじゃないか?」と思った事を試しにやってみたテストプログラムです。セキュリティ諸々に関しての対策などはほとんど行っていませんので、使用には十分注意してください。

また、このプログラムによって生じるいかなるトラブルや損害の責任を負いかねますので、自己責任でご利用ください。

1:まず紹介されていたsosumiをダウンロードしてください。ダウンロードはこちらから。

2:通知したい場所リストを格納する「location.txt」ファイルを作ります。
中身はカンマ区切りでこんな感じで。
ユニークid,場所の緯度,場所の経度,通知方法,通知メッセージ,0

例:
1,12.345678,123.456789,message,家に着いたらまずうがいだよ!,0
2,34.567890,123.567890,mail,仕事場に着いたね。今日も頑張ろう!,0
3,56.789012,123.7678901,message,気になってたお店「xxx」はこの近くだよ,0

緯度経度の取得はこことかで調べられます。

3:通知履歴を残す「log.txt」を用意。中身は空でOK。

4:以下のプログラムpush.phpを用意。2点間の距離の計算は「緯度、経度から距離と向きを算出::中年プログラマblog」のGeoDistance()を利用させていただきました。

push.php

<?
require_once('class.sosumi.php');

//********************************//
//  設定
//********************************//

//mobilemeアカウント
$username='ユーザ名';
$password='パスワード';

//通知方法がメールの時のメールアドレス
$mail_address = 'メールアドレス';

//通知方法がメールの時のメールのタイトル
$mail_subject = '地点到着メッセージ';

//iphoneの場所が報告地点の半径[$report_distance]メートル以内に入ったら報告
$report_distance=150;

//場所リストが格納されたファイル
$location_file = 'location.txt';

//ログファイル
$log_file = 'log.txt';

//********************************//
//  処理開始
//********************************//

$ssm = new Sosumi($username, $password);

$location_data = $ssm->locate();    //iponeの場所
$location_list = file($location_file);  //登録しといた場所リスト

$flg=false;
$new_location_data='';
$message='';
foreach($location_list as $line)
{
    $data = explode(',', str_replace("\n", "", $line));

    if($data[5]==0)
    {
        $distance = GeoDistance($location_data->latitude, $location_data->longitude, $data[1], $data[2], 3);

        if($distance < $report_distance)
        {
            $flg=true;
            $data[5]=1;
            $message = $data[4];

            if($data[3]=='message') $ssm->sendMessage($data[4]);
            elseif($data[3]=='mail') mail($mail_address , $mail_subject , $data[4]);

            writeLog($log_file, $data[0]);
        }
        else
        {
            $data[5]=0;
        }
    }

    $new_location_list .= implode(',', $data)."\n";
    $cnt++;
}

if($flg==true)
{
    updateLocationFile($location_file, $new_location_list);
}

//ログ書き込み
function writeLog($log_file, $id)
{
    if(empty($log_file)) return false;

    file_put_contents($log_file, date("Y-m-d H:i:s").",場所データ[".$id."]を実行しました。\n", FILE_APPEND); 

}

//場所データ更新
function updateLocationFile($location_file=null, $new_data=null)
{
    if(empty($location_file)) return false;

    $fp = fopen($location_file, 'w');
    fputs($fp, $new_data);
    fclose($fp);
}

//距離算出
function GeoDistance($lat1,$lng1,$lat2,$lng2,$decimal ){
    if( (abs($lat1-$lat2) < 0.00001) && (abs($lng1-$lng2) < 0.00001) ){
        $distance = 0;
    }else{
        $lat1 = $lat1*pi()/180;$lng1 = $lng1*pi()/180;
        $lat2 = $lat2*pi()/180;$lng2 = $lng2*pi()/180;

        $A = 6378140;
        $B = 6356755;
        $F = ($A-$B)/$A;

        $P1 = atan(($B/$A)*tan($lat1));
        $P2 = atan(($B/$A)*tan($lat2));

        $X = acos( sin($P1)*sin($P2) + cos($P1)*cos($P2)*cos($lng1-$lng2) );
        $L	= ($F/8)*( (sin($X)-$X)*pow((sin($P1) + sin($P2)),2)/pow(cos($X/2) ,2) - (sin($X)-$X)*pow(sin($P1)-sin($P2),2)/pow(sin($X),2) );

        $distance = $A*($X+$L);
        $decimal_no=pow(10,$decimal);

        $distance = round($decimal_no*$distance)/$decimal_no;
    }

    $format='%0.'.$decimal.'f';
    return sprintf($format,$distance);
}
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<META NAME="ROBOTS" CONTENT="NOINDEX,NOFOLLOW,NOARCHIVE">
<title>近くになったらお知らせ</title> 

<?if(! empty($message)){echo("以下のメッセージが通知されました。<br><br>「".  $message . "」");}?>

</body></html>

5:合計4つのファイルをすべて同じ階層にアップロード。.txtファイルはパーミッション「666」に。
class.sosumi.php
push.php
location.txt
log.txt

以上です。push.phpにアクセスすればMobileMe経由でiPhoneの場所を取得して、その場所で通知するメッセージがあれば、アラートメッセージを通知するかメールを送信します。push.phpにアクセスする処理を定期的におこなうようにcronなどで設定しておく必要がありますね。

IMG_0358.PNG

よくあるウェブサービスでは、あらかじめ設定した時刻に予定を通知するリマインダー機能というのはあるのですが、設定した場所に着いたら通知する機能というのはないんですよね。

iPhoneアプリなどで現在地に関する情報を表示するアプリはあるのですが、それらも、アプリをまず起動しなければならないのです。こちら始まりなわけです。

例えば家に着いたらやらなければいけない事をあらかじめ設定しておいても、家についてアプリを起動するのを忘れたら予定に気づかず意味がないわけです。メモっておいてもメモを見る事に気づかなければ意味が無いわけです。

家に着いたら「xxxxするのを忘れるなよ!」とプッシュ通知してくれたら、忘れるもなにも向こう側から教えてくれるわけですから頼もしいわけです。

「その場所に訪れたらやるべき事」を通知してくれるリマインダー機能と言う事です。

日本のケータイにはこういうサービスがありそうな気もしますが、こういった通知機能は欲しいですね。サーバなどを介さなくても、iPhoneで常駐アプリが許可されれば可能かもしれませんね。

「やるべきことがあったのにその場所を通り過ぎてしまった!」「 店で買おうと思っていたものを忘れてしまった!」 このように「ある特定の場所」でやるべきだったタスクを忘れてしまうということは誰にでもあると思います。

OmniFocus では、「家」や「オフィス」または特定の「店」「コンビニ」「駅」「書店」などを GPS で登録しておくことで、「この場所に近付いたらタスクが表示される」という細工をほどこすことができます。
「ああ!あそこでこれやるつもりだったのに!」をなくす OmniFocus for iPhone | Lifehacking.jp

まさに僕がやりたいのはこれだったです!僕もOmniFocusを利用しているので、いずれ自動でタスクを表示してくれたら嬉しいですね。

この機能があればなんかすごく面白いサービスが沢山生まれそうな気がするわけです!

1:Program, iPhone

  1. 2009年12月02日 at 03:09 | #1

    最近1週間くらいのことですが、Todoが設定されている場所に近づくとiPhoneにプッシュ通知されるiPhoneアプリを探していました。
    なくてあきらめかけて、それでも検索キーワードをいろいろ変えて検索していたところ、こちらの記事を発見!

    さっそくサーバーに組み込んだんところ、ちゃんとプッシュ通知されました。
    感謝感激です。

  2. 2009年12月02日 at 15:56 | #2

    >もへぢさん
    使ってくれてありがとうございました!

    「Todoが設定されている場所に近づくとiPhoneにプッシュ」
    こういったものがアプリで登場してくれると、いろんなシーンで役立つと思うんですけどね!

  1. 2009年07月10日 at 00:11 | #1