GoogleHomeに潮汐情報をしゃべらせるようにして満足はしていたのですが、使っていると面倒なことも出てくるもので・・・
大きくは二つです
・明日の名古屋は?ときいても、2017年11月10日の・・・みたいに言われて長い。
・そもそも、今いるところに近いところの情報が聞きたいわけで、名古屋は?とか面倒。
一つ目は、「明日の」と聞いているので、そのまま「明日の」としゃべってもらえればよいです。リクエストのJSONを見てみると
["result"]=>
object(stdClass)#15 (10) {
["source"]=>
string(5) "agent"
["resolvedQuery"]=>
string(27) "明日の名古屋の潮は"
["speech"]=>
string(0) ""
["action"]=>
string(9) "calc_tide"
["actionIncomplete"]=>
bool(false)
["parameters"]=>
object(stdClass)#16 (2) {
["date"]=>
string(10) "2017-11-10"
["geocity"]=>
string(9) "名古屋"
}
["contexts"]=>
array(3) {
[0]=>
object(stdClass)#17 (3) {
["name"]=>
string(32) "actions_capability_screen_output"
["parameters"]=>
object(stdClass)#18 (4) {
["date"]=>
string(10) "2017-11-10"
["date.original"]=>
string(6) "明日"
["geocity.original"]=>
string(9) "名古屋"
["geocity"]=>
string(9) "名古屋"
}
["lifespan"]=>
int(0)
}
result->contexts[0]->parameters->date.originalに情報があるので、それが使えそうです。収集してそれを出すように変えます。
if($action == "calc_tide") {
$date = $json->result->parameters->date;
list($year, $month, $day) = split("-", $date);
$portName = $json->result->parameters->geocity;
$dateStr = $json->result->contexts[0]->parameters->{'date.original'};
$message = createTideMessage($year, $month, $day, $dateStr, $portName);
speak($message);
}
これは簡単ですね。
次に、位置情報です。位置情報はFirebaseを使う場合のサンプルはあるのですが、JSONを自分で触る時の情報は全然ないのですよね・・・
まず、Default Welcome IntentをWebHookを使うようにします。Defaukl Welcome Intentは、プログラム側で受ける場合には、input.welcomというアクションになるのですが、これで緯度経度を取得したいという権限がほしいというJSONを返すようにします。
if($action == "calc_tide") {
$date = $json->result->parameters->date;
list($year, $month, $day) = split("-", $date);
$portName = $json->result->parameters->geocity;
$dateStr = $json->result->contexts[0]->parameters->{'date.original'};
$message = createTideMessage($year, $month, $day, $dateStr, $portName);
speak($message);
} else if($action == "input.welcome") {
echo '
{
"speech": "PLACEHOLDER_FOR_PERMISSION",
"data": {
"google": {
"expectUserResponse": true,
"isSsml": false,
"noInputPrompts": [],
"systemIntent": {
"intent": "actions.intent.PERMISSION",
"data": {
"@type": "type.googleapis.com/google.actions.v2.PermissionValueSpec",
"optContext": "近くの港を検索するため",
"permissions": [
"DEVICE_PRECISE_LOCATION"
]
}
}
}
}
} ';
}
返すJSONについては、この辺りが詳しいです。
今回は緯度経度だけなので、DEVICE_PRECISE_LOCATIONを指定していますが、NAMEを指定すると名前が、DEVICE_COARSE_LOCATIONを指定すると住所が取得できます。
これで、Google Assistantに接続したときに、情報を取得してよいか?というメッセージが表示されます。
IntentでDefault Welcome IntentのFollowUp Intentを作ります。このFollowUp Intentで、情報取得してよいか?の結果を受け取ります。Default Wlecome Intentの右の方にカーソルを持っていくと、Add follow-up intentというのが表示されますので、それをクリックします。
クリックするとメニューが表示されますので、fallbackを選択します。
中を変更する必要はありません。必要であれば、WebHookを呼んでサーバ側に登録するというのもありかもしれません。
次に、内部的には、actions_intent_PERMISSION上記の結果を受けるIntentを追加します。
Eventsにactions_intent_PERMISSIONというイベントを追加します。
これにもWebhookを追加しておきます。
このイベントは、action名を、set_locationとしておくことにします。
これで、接続(action:input.welcome) →パーミッション取得 → パーミッション取得イベント(action: set_location)という流れができました。
PHP側にもコードを追加します。
if($action == "calc_tide") {
$date = $json->result->parameters->date;
list($year, $month, $day) = split("-", $date);
$portName = $json->result->parameters->geocity;
$dateStr = $json->result->contexts[0]->parameters->{'date.original'};
$message = createTideMessage($year, $month, $day, $dateStr, $portName);
speak($message);
} else if($action == "input.welcome") {
echo '
{
"speech": "PLACEHOLDER_FOR_PERMISSION",
"data": {
"google": {
"expectUserResponse": true,
"isSsml": false,
"noInputPrompts": [],
"systemIntent": {
"intent": "actions.intent.PERMISSION",
"data": {
"@type": "type.googleapis.com/google.actions.v2.PermissionValueSpec",
"optContext": "近くの港を検索するため",
"permissions": [
"DEVICE_PRECISE_LOCATION"
]
}
}
}
}
} ';
} else if($action == "set_location") {
$tide = new tide_base();
if(isset($json->originalRequest->data->device)) {
$lat = $json->originalRequest->data->device->location->coordinates->latitude;
$lng = $json->originalRequest->data->device->location->coordinates->longitude;
$nearPort = $tide->getNearPort($lat, $lng);
$nearPortAll = $tide->getNearPortAll($lat, $lng);
$port = $tide->minatoAll;
$nearPortName = $port[$nearPort][0];
$nearPortNameAll = $port[$nearPortAll][0];
if($nearPort == $nearPortAll) {
$message = "一番近い港は" . $nearPortName . "です。";
$message = createTideMessage($year, $month, $day, "今日", $nearPortName);
} else {
$message = "一番近い港は" . $nearPortNameAll . "ですが主要4分潮の計算しかできません。60分潮>の計算ができる一番近い港は" . $nearPort + "です。";
$message = createTideMessage($year, $month, $day, "今日", $nearPortNameAll);
}
} else {
$message = "登録なしで進めます。";
}
speak($message);
}
さてテストしてみましょう。
沓形ってどこ?
画面上小さくなっているため見えないのですが、デフォルトではシミュレーターの場所が、MountainViewになっていますね。右上のLocationで変更してやります。
ちなみに、MountainViewからだと、沓形が一番近いのかな?
場所を東京にして見ます。
いい感じにできました!



















































