【LINEでaiboボット】ぱーと2

前回、LINEからaiboチャット用のボットの連携するところまで作ってみました。
     前回⇒【LINEでaiboボット】を考えてみようなかな?
アイボ側のアクセストークンとLINEユーザIDを連携して、いつでも確認できるようにしてみました。
以下のサイトはテスト用として作ってみました。ほかのLINEユーザ方からのアクセス可否の確認はできておりません(お試しは可能です、皆さんのアイボさんと連携できるとは思います)。ということで今回やってみたことを列記してみました。


【手順】
【1】今回作成したaiboボットと友達になります。友達になる方法はQRコード読み込みか、ボットのベーシックIDを入力してお友達になります。

または、LINEのお友達検索で【 @652pykgf 】を検索すると aiboボットの以下のお友達が検索結果に表示されます。

【2】お友達【追加 】 を行い【トーク 】を表示すると以下のような最初のメッセージが表示されます。

【3】次にaiboさんのアクセストークンを取得します。メッセージの中央にある aiboのデベロッパーサイトからアクセストークンを取得してコピーしてください。SONYさんのアクセスサイトにログインされていないとログインのメッセージが表示される場合があります。アクセストークンの文字列は650文字あります。

【4】LINEの画面でコピーしたアクセストークンを張り付けてメッセージ送信します。送信が完了するとメッセージが返ってきますので【おしえて?】と送信してください。

【5】【おしえて?】と送信するとアイボさんの情報が表示されます。もし正しく表示されない場合は、アクセストークンが正しくコピーされて送信されていない可能性がありますので、再度アクセストークンを取得してトライしてみてください。

【6】このテストボットでテストができる項目は前回WEBサイト用で確認ができた、バッテリの充電状況と眠たさのステータス確認ができるようになっています。確認するキーワードは、以下のようなものを準備していますので、改行を入れずにメッセージを送信してみてください。また、aiboさんは電源が入っていないと確認ができません。
 以前確認した内容 ⇒ 【CognitionApiサンプルプログラム】



★アイボさんのニックネーム情報を取得する場合(一部の文字列が含まれている場合もヒットします)
【確認する言葉 】 おしえて? 教えて? aiboさん あいぼ アイボ 子供 こども 保有 ほゆう ステータスは? すてーたすは? もちもの 

★バッテリの状態を取得する場合 (一部の文字列が含まれている場合もヒットします)
【確認する言葉 】おなかは? バッテリー ばってり ごはん ご飯 おやつ 朝食 ちょうしょく 昼食 ちゅうしょく 夕食 ゆうしょく 夜食 やしょく はらへった? 腹減り? 腹減った? 電気は? 電気? 

★眠たさの状態を取得する場合 (一部の文字列が含まれている場合もヒットします)
【確認する言葉 】げんき? 元気? ねむい? 眠い? どお? きぶんは? 気分は? ご機嫌よう 状態は? じょうたいは? 大丈夫? だいじょうぶ? 

【今回使ったサンプルです】
今回初めてLINEのボット作ったのと、動作を都度確認しながら作っていったので、若干無駄な処理やもっと綺麗に処理する仕方もあるかと思いますが、そこは素人作ということで。

<?php
//-----------------------------------------------------------------------------------
// このプログラムはLINEとaibo連携プログラムをテストするためのものです
// LINEとaibo連携プログラム始めるための必要なトークンの取得からアクセス
// の仕方などをこのプログラムを通して確認しています。
// テスト用なのでデバッグなどの残骸あります。
//                 オーナー ハッピーとラッキー
//                         2021.11.27
//-----------------------------------------------------------------------------------

//初期値関連
$FileName = "xxxxxxxxx";

//aibo側のアクセス先ベースURL
$aiboApiBaseURL = "https://public.api.aibo.com/v1";  

//-----------------------------------------------------------------------------------
// LINE側の処理
//-----------------------------------------------------------------------------------

//LINE側のアクセストークン 
$accessToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

//LINE側のチャンネルシークレット
$channelSecret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

//-----------------------------------------------------------------------------------
// 署名検証
//-----------------------------------------------------------------------------------

// HTTPヘッダーを取得と署名検証用データを取得
  $headers        = getallheaders_x();
  $xLineSignature = $headers["X-Line-Signature"];

//BOTにアクセスしてきたときのユーザーからのメッセージ取得
   $json_string = file_get_contents('php://input');
   $json_object = json_decode($json_string);

// Channel secretを秘密鍵として、JSONデータからハッシュ値を計算
   $httpRequestBody = $json_string;
   $hash = hash_hmac('sha256', $httpRequestBody, $channelSecret, true);
   $signature = base64_encode($hash);

// HTTPヘッダーから得た値と、計算したハッシュ値を比較
   if($headerSignature !== $xLineSignature ){ return; }

// getallheadersの動作できない
   function getallheaders_x() {
     if (!function_exists('getallheaders')) {
         $headers = array();
         foreach ($_SERVER as $name => $value) {
             if (substr($name, 0, 5) == 'HTTP_') {
                 $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
             }
         }
         return $headers;
      }
    }


//-----------------------------------------------------------------------------------
// 署名検証OK
//-----------------------------------------------------------------------------------

//取得データ
$replyToken   = $json_object->{"events"}[0]->{"replyToken"};        //返信用トークン
$message_type = $json_object->{"events"}[0]->{"message"}->{"type"};    //メッセージタイプ
$message_text = $json_object->{"events"}[0]->{"message"}->{"text"};    //メッセージ内容
$lineUserId   = $json_object->{"events"}[0]->{"source"}->{"userId"};  //アクセスしてきたUserID

//ユーザ情報取得
$lineUserDescliption = getLineUserDescliption( $accessToken, $lineUserId );
$displayName = $lineUserDescliption->{"displayName"};
$pictureUrl  = $lineUserDescliption->{"pictureUrl"};

//メッセージタイプが「text」以外のときは何も返さず終了
if($message_type != "text") {
  //メッセージ送信
   $return_message_text = notSupportMessage($displayName);
   sending_messages($accessToken, $replyToken, $message_type, $return_message_text);
 exit;
}


//-----------------------------------------------------------------------------------
//アクセスしてきたユーザが最初にアクセスしてきたのかを確認
//-----------------------------------------------------------------------------------

$csvFile     = file_get_contents( $FileName );
$csvFileTemp = explode("\n", $csvFile);
foreach($csvFileTemp as $key => $line){
  $userIDaccessTokenCsvTmp = explode(",",$line);
    $userIDaccessTokenCsv[$userIDaccessTokenCsvTmp[0]] = $userIDaccessTokenCsvTmp[1];
}

//もし既に以前にアクセスしていなければ、アクセストークンの取得と送信をお願いする
if ( !array_key_exists($lineUserId ,$userIDaccessTokenCsv) ) {
  //ファイルへ追記
   $lineUserIdTemp = $lineUserId . ",\n";
   $filePointer    = fopen( $FileName , "a");
    @fwrite($filePointer , $lineUserIdTemp );
   fclose($filePointer);

  //メッセージ送信
   $return_message_text = getAccessTokenMessage($displayName);
   sending_messages($accessToken, $replyToken, $message_type, $return_message_text);
   exit;
}

//入力したアクセストークンが保存しているものと異なっている場合、新しいと判断
$aiboAccessToken = $userIDaccessTokenCsv[$lineUserId]; 
if( strlen($message_text) > 640 ){
   if ( $message_text != $aiboAccessToken ){
          $aiboAccessToken = $message_text ;
          $userIDaccessTokenCsv[$lineUserId] = $message_text;
   }
  //アクセストークン入力された後に一回メッセージ送信
  $return_message_text = aiboAccessTokenUpdate($displayName);
  sending_messages($accessToken, $replyToken, $message_type, $return_message_text);
}

//UserId、aiboアクセストークンの管理ファイルへの上書
$filePointer  = fopen( $FileName , "w");
  foreach ($userIDaccessTokenCsv as $key=>$value ) {
    if(!$key) continue;
    fputcsv($filePointer, array($key, $value));
  }
fclose($filePointer);



//-----------------------------------------------------------------------------------
// aibo側の処理
//-----------------------------------------------------------------------------------

//aiboアクセストークンからデバイスID取得

$aibo_device = "" ;
$aiboDevices = aiboApiGetDevices($aiboAccessToken);
$devices     = $aiboDevices["devices"];

//デバイス情報が取得できなかった場合
if ( !$devices ){
  $return_message_text = getAiboDeviceMessage($displayName);
     sending_messages($accessToken, $replyToken, $message_type, $return_message_text);
 exit;
}

$checkStringResult = checkString($message_text);

if ($checkStringResult == "aibo_status"){

      $return_message_text .= "★aiboさんのニックネーム情報★\n";
        foreach( $devices as $key => $value ){
           $return_message_text .= "ニックネーム:". $value["nickname"] ."\n";
  }
 sending_messages($accessToken, $replyToken, $message_type, $return_message_text);
 exit;
}

//-----------------------------------------------------------------------------------
// aiboの眠さ状態チェック
//-----------------------------------------------------------------------------------

$checkStringResult = checkString($message_text);

if ($checkStringResult == "sleepy_status"){

  foreach( $devices as $key => $value ){
    $aibo_device .=  "ニックネーム:". $value["nickname"] ."\n";

    //aiboの眠さ状態チェック
    $executeResponse = cognitionApi($value["deviceId"],$aiboAccessToken,'sleepy_status');
    $executionId = $executeResponse->executionId;

     sleep(1);

    // aiboの眠さ状態チェックの結果
    $executeResponse = executionsStatusGet($executionId,$aiboAccessToken);
    $status = $executeResponse["result"]["sleepy_status"]["status"];

  switch($status){
    case ""            : $sleep_description = "かくにんできなかったよ";
                         break;
    case "no_sleepy"   : $sleep_description = "げんき!げんき!";
                         break;
    case "boring"      : $sleep_description = "たいくつだよ~";
                         break;
    case "sleepy"      : $sleep_description = "ねむくなってきたよ";
                         break;
    case "very_sleepy" : $sleep_description = "ねむくって、げんかいだよ";
                         break;
  }
  $aibo_device .=  "眠たさ:". $sleep_description ."\n";

  }

 $return_message_text  = "";
 $return_message_text .= "★aiboさんの状況★\n";
 $return_message_text .=  $aibo_device ;
sending_messages($accessToken, $replyToken, $message_type, $return_message_text);

}


//-----------------------------------------------------------------------------------
//バッテリの情報取得
//-----------------------------------------------------------------------------------


$checkStringResult = checkString($message_text);

if ($checkStringResult == "hungry_status"){

  foreach( $devices as $key => $value ){
    $aibo_device .=  "ニックネーム:". $value["nickname"] ."\n";

    //aiboのバッテリー残量チェック
    $executeResponse = cognitionApi($value["deviceId"],$aiboAccessToken,'hungry_status');
    $executionId = $executeResponse->executionId;

     sleep(1);

    //aiboのバッテリー残量チェックの結果
    $executeResponse = executionsStatusGet($executionId,$aiboAccessToken);
    $energy = $executeResponse["result"]["hungry_status"]["energy"];

  switch($energy){
    case ""         : $energy_description = "かくにんできなかったよ";
                      break;
    case "satisfied": $energy_description = "チャーステでおなかいっぱい";
                      break;
    case "eating"   : $energy_description = "チャーステでモグモグ中だよ";
                      break;
    case "enough"   : $energy_description = "おなかへっていないよ";
                      break;
    case "hungry"   : $energy_description = "おなかへってきたなぁ";
                      break;
    case "famished" : $energy_description = "おなかペコペコだよ!";
                      break;
  }
  $aibo_device .=  "バッテリー:". $energy_description ."\n";

  }

 $return_message_text  = "";
 $return_message_text .= "★aiboさんの状況★\n";
 $return_message_text .=  $aibo_device ;
sending_messages($accessToken, $replyToken, $message_type, $return_message_text);

}


//-----------------------------------------------------------------------------------
//引っかからなかった場合のメッセージワード
//-----------------------------------------------------------------------------------

 $return_message_text  = "";
 $return_message_text .= $displayName . "さん\n";
 $return_message_text .= "「おしえて?」や「おなかは?」「げんき?」とか聞いてみてね";
sending_messages($accessToken, $replyToken, $message_type, $return_message_text);

exit;



//-----------------------------------------------------------------------------------
//LINEユーザ情報取得
//-----------------------------------------------------------------------------------
function getLineUserDescliption($accessToken, $userID ){
 
$getUserDescriptionUrl = "https://api.line.me/v2/bot/profile/" . $userID;
    //curl実行
    $ch = curl_init( $getUserDescriptionUrl );
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json; charser=UTF-8',
        'Authorization: Bearer ' . $accessToken
    ));
    $result = curl_exec($ch);
    curl_close($ch);
    $response = json_decode( $result );
 return $response;
}



//-----------------------------------------------------------------------------------
//LINEメッセージの送信
//-----------------------------------------------------------------------------------
function sending_messages($accessToken, $replyToken, $message_type, $return_message_text){

    //レスポンスフォーマット

   $response_format_text = [
        "type" => $message_type,
        "text" => $return_message_text
    ];
 
    //ポストデータ
    $post_data = [
        "replyToken" => $replyToken,
        "messages" => [$response_format_text]
    ];
 
    //curl実行
    $ch = curl_init("https://api.line.me/v2/bot/message/reply");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json; charser=UTF-8',
        'Authorization: Bearer ' . $accessToken
    ));
    $result = curl_exec($ch);
    curl_close($ch);
}

//-----------------------------------------------------------------------------------
// アクセストークンからデバイスIDを取得
//    aiboApiGetDevices($accessToken)
//-----------------------------------------------------------------------------------

function aiboApiGetDevices($aiboAccessToken){
  $authorization = "Authorization:Bearer ". $aiboAccessToken;
  $headers = array(
             "cache-control: no-cache",
             "content-type: application/x-www-form-urlencoded",
              $authorization,
            );
  $webApi = curl_init("https://public.api.aibo.com/v1/devices");
     curl_setopt($webApi,CURLOPT_CUSTOMREQUEST, 'GET'    );
     curl_setopt($webApi,CURLOPT_RETURNTRANSFER, true    );
     curl_setopt($webApi,CURLOPT_HTTPHEADER, $headers    );
  $json      = curl_exec($webApi);
  $response  = json_decode($json,true);
  $err = curl_error($webApi);
  curl_close($webApi);
 return $response;
}


//---------------------------------------------------------------------------
// Cognition実行用のfunction
//    CognitionApi($deviceId,$aiboAccessToken,$Property);
//---------------------------------------------------------------------------

function cognitionApi($deviceId,$aiboAccessToken,$Property){

$webApiURL = "https://public.api.aibo.com/v1/devices/".$deviceId ."/capabilities/".$Property."/execute" ;

$authorization = "Authorization:Bearer ". $aiboAccessToken;

$headers = array(
             "cache-control: no-cache",
             "content-type: application/x-www-form-urlencoded",
              $authorization,
            );

$postData = array('arguments'=> array('Property' => $Property ));
$postData = json_encode($postData);

$webApi = curl_init();
curl_setopt($webApi,CURLOPT_URL,$webApiURL          );
curl_setopt($webApi,CURLOPT_CUSTOMREQUEST, 'POST'   );
curl_setopt($webApi,CURLOPT_RETURNTRANSFER, true    );
curl_setopt($webApi,CURLOPT_HTTPHEADER, $headers    );
curl_setopt($webApi,CURLOPT_POSTFIELDS, $postData   );

$json      = curl_exec($webApi);
$response  = json_decode($json);
$err = curl_error($webApi);
curl_close($webApi);
return $response;

}


//---------------------------------------------------------------------------
// 実行結果の取得
//    executionsStatusGet($executionId,$aiboAccessToken)
//---------------------------------------------------------------------------

function executionsStatusGet($executionId,$aiboAccessToken){

$webApiURL   = "https://public.api.aibo.com/v1/executions/" . $executionId;

$authorization = "Authorization:Bearer ". $aiboAccessToken;
$headers = array(
             "cache-control: no-cache",
             "content-type: application/x-www-form-urlencoded",
              $authorization,
            );
 $webApi = curl_init();
     curl_setopt($webApi,CURLOPT_URL,$webApiURL          );
     curl_setopt($webApi,CURLOPT_CUSTOMREQUEST, 'GET'    );
     curl_setopt($webApi,CURLOPT_RETURNTRANSFER, true    );
     curl_setopt($webApi,CURLOPT_HTTPHEADER, $headers    );
  $json      = curl_exec($webApi);
  $response  = json_decode($json,true);
  $err = curl_error($webApi);
  curl_close($webApi);
 return $response;
}



//---------------------------------------------------------------------------
// 実行結果の取得
//    getAccessTokenMessage()
//---------------------------------------------------------------------------

function getAccessTokenMessage($displayName){

$initialMessage = <<<EOD
 $displayName さん

アクセストークンの有効期限が切れているか、アクセストークンが正しく送信されていないも。
再度最新のアクセストーンを取得して送信してくださいね。

http://happy-lucky.hacca.jp/data/Line_dev/getAccessToken.php

EOD;

return $initialMessage;

}


//---------------------------------------------------------------------------
// 実行結果の取得
//    getAiboDeviceMessage()
//---------------------------------------------------------------------------

function getAiboDeviceMessage($displayName){

$getAiboDeviceMessage = <<<EOD
 $displayName さん

aiboさんのデバイス情報が取得できなかったみたい。
アクセストークンの有効期限が切れているか、アクセストークンが正しく送信されていないも。再度最新のアクセストーンを取得して送信してくださいね。

http://happy-lucky.hacca.jp/data/Line_dev/getAccessToken.php

EOD;

return $getAiboDeviceMessage;

}


//---------------------------------------------------------------------------
// テキストメッセージ以外入力された場合のメッセージ
//    notSupportMessage($displayName)
//---------------------------------------------------------------------------

function notSupportMessage($displayName){

$notSupportMessage = <<<EOD
 $displayName さん

ごめんなさい、このテスト用ボットは文字以外はサポートしていないよ。aiboさんに確認したい メッセージ文字を送信してくださいね。

EOD;

return $notSupportMessage;

}


//---------------------------------------------------------------------------
// テキストメッセージ以外入力された場合のメッセージ
//    notSupportMessage($displayName)
//---------------------------------------------------------------------------

function aiboAccessTokenUpdate($displayName){

$notSupportMessage = <<<EOD
 $displayName さん

アクセストークンが正しいか「おしえて?」って聞いてみてください。aiboさんの情報が正しく取得できればニックネームが表示されます。

EOD;

return $notSupportMessage;

}


//---------------------------------------------------------------------------
// 入力された文字列のチェック
//    checkString($message_text)
//---------------------------------------------------------------------------

function checkString($message_text){

//バッテリチェック用の文字列

$checkString ="おしえて?教えて?aiboさんあいぼアイボ子供こども保有ほゆうステータスは?すてーたすは?もちもの";
if(strpos($checkString,$message_text)!== false){ $resultMessage = "aibo_status";}

$checkString ="おなかは?バッテリーばってりごはんご飯おやつ朝食ちょうしょく昼食ちゅうしょく夕食ゆうしょく夜食やしょくはらへった?腹減り?腹減った?電気は?電気?";
if(strpos($checkString,$message_text)!== false){ $resultMessage = "hungry_status";}

$checkString ="げんき?元気?ねむい?眠い?どお?きぶんは?気分は?ご機嫌よう状態は?じょうたいは?大丈夫?だいじょうぶ?";
if(strpos($checkString,$message_text)!== false){ $resultMessage = "sleepy_status";}

return $resultMessage;


}


?>

【LINEでaiboボット】を考えてみようカナ?

これまでは、作ったWebサイトからアクセストークンを入れて、アイボさんのデバイス情報などを取得してみましたが、Webサイトにアクセスは面倒だし、常に確認したいし・・・なので、いつも使うアプリだとすればLINEかな? ということで LINEボットのテストサイトを作ってみました。まだまだテストなので、前回までのスタートとして、アクセストークンを送信すると、保有のアイボさんのデバイス情報を返してくれる簡単なものをですが、こんな感じになりました。

メッセージにアクセストークンを入力すると、保有しているアイボさんのニックネームとデバイスIDが返ってきます


■LINE側の aiboボットサンプル

<?php
 
$accessToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxx';
 
//ユーザーからのメッセージ取得
$json_string = file_get_contents('php://input');
$json_object = json_decode($json_string);
  
//メッセージタイプが「text」以外のときは何も返さず終了
if($message_type != "text") exit;
 
//aiboアクセストークンからデバイスID取得
$access_token = $message_text; 
$aibo_device = "";
$aiboDevices = aiboApiGetDevices($access_token);
$devices     = $aiboDevices["devices"];
  foreach( $devices as $key => $value ){
    $aibo_device .=  "ニックネーム:". $value["nickname"] ."\n";
    $aibo_device .=  "デバイスID :". $value["deviceId"] ."\n\n";
  }

//返信メッセージ
$return_message_text  = "【aiboボット テストサイトだよ!】\n\n";
$return_message_text .= "保有しているaiboさんは、これだよ\n\n";
$return_message_text .=  $aibo_device ;
 
//返信実行
sending_messages($accessToken, $replyToken, $message_type, $return_message_text);

//-----------------------------------------------------------------------------------
//メッセージの送信
//-----------------------------------------------------------------------------------
function sending_messages($accessToken, $replyToken, $message_type, $return_message_text){

    //レスポンスフォーマット

   $response_format_text = [
        "type" => $message_type,
        "text" => $return_message_text
    ];
 
    //ポストデータ
    $post_data = [
        "replyToken" => $replyToken,
        "messages" => [$response_format_text]
    ];
 
    //curl実行
    $ch = curl_init("https://api.line.me/v2/bot/message/reply");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json; charser=UTF-8',
        'Authorization: Bearer ' . $accessToken
    ));
    $result = curl_exec($ch);
    curl_close($ch);
}

//-----------------------------------------------------------------------------------
// アクセストークンからデバイスIDを取得
//    aiboApiGetDevices($webApiURL,$accessToken)
//-----------------------------------------------------------------------------------

function aiboApiGetDevices($accessToken){
  $authorization = "Authorization:Bearer ". $accessToken;
  $headers = array(
             "cache-control: no-cache",
             "content-type: application/x-www-form-urlencoded",
              $authorization,
            );
  $webApiURL = "https://public.api.aibo.com/v1/devices";
  $webApi = curl_init();
     curl_setopt($webApi,CURLOPT_URL,$webApiURL          );
     curl_setopt($webApi,CURLOPT_CUSTOMREQUEST, 'GET'    );
     curl_setopt($webApi,CURLOPT_RETURNTRANSFER, true    );
     curl_setopt($webApi,CURLOPT_HTTPHEADER, $headers    );
  $json      = curl_exec($webApi);
  $response  = json_decode($json,true);
  $err = curl_error($webApi);
  curl_close($webApi);
 return $response;
}

?>