googlehomeからps4を操作

googlehomeからps4を操作

はじめに

googlehomeで操作できる機器を増やしていきます。
今回はps4の「起動」「スタンバイ」「アプリの起動」ができる様にしていきます。

基本的にはこちらの記事の二番煎じです。
ただ普段pythonばかり書いていてjavascriptに馴染みがない私は
アロー関数が飛び交うオシャレすぎるコードについていけませんでした。
本記事ではもうちょっと他言語っぽい(≒初心者向け)のコードに直しています。
ついでにうっかりハマったところも紹介します。

全体像

ハマりどころ

Firebaseに登録したらRealtimeDatabaseの構成を定義するのですが、どうもうまくいかない。
というか、見た目が違うからあっているかよくわかない。

原因は、「Realtime Databaseが選択されていないこと」でした

赤で囲まれた部分がずっと「Cloud Firestore」になっていました。
正しいメニューを選択したら狙った通りデータを構成できました。

私の場合は上図の様な構成になっています。
また、ルールも上図の通り、.read .write共にtrueにしています。
このままでは、プロジェクト名とデータベースの構成が分かっている人なら誰でも読み書きできてしまいます。
今のところデータを書き換えられたところで困る様なこともないのでこのまま進めますが、
のちのち修正しようと思います。

完成したプログラム

参考にした記事では1つのプログラムにまとめていたのですが、
読みやすさと今後の拡張性を考慮して3つのファイルに分けました。
同一フォルダに入れておく必要があります。

index.js

//firebaseとその他必要なファイルをインポート
var firebase = require("firebase")
var ps4 = require("./ps4.js")	//ps4操作に関わる処理を記載
var fnc = require("./functions.js")	//いろんなプログラムで使うことになりそうな関数をまとめて記載

//firebaseのconfig
var firebaseConfig = {
        apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        authDomain: "project-name.firebaseapp.com",
        databaseURL: "https://project-name.firebaseio.com",
        projectId: "project-name",
        storageBucket: "project-name.appspot.com",
        messagingSenderId: "9999999999999",
        appId: "1:99999999999:web:c6bxx99xx99xx99x99"
      };

firebase.initializeApp(firebaseConfig);



//dbに接続する準備
const path = "/googlehome";
const keyword = "action";
var db =firebase.database();
var ref = db.ref(path);

//以下の形で待ち受けると、db更新時にfunctionが起動する(いわゆるリスナー)
//dbから呼び込まれたデータをsnapshotとして引数に設定する。
ref.on("value",function(snapshot){
    //snapshot.val()でjson形式のデータを取得できる。
    //functions.jsに作ったgetJsonData関数を使って、必要な部分だけを取り出す。
    var action = fnc.getJsonData("action",snapshot.val());

    // actionには「ps4 起動」のような文字列が入っている
    // action.split(" ")で単語ごとの配列に分解し、
    //1つ目の要素(上の例なら「ps4」)を取り出して場合分けする
    switch (action.split(" ")[0]) {

        //ひとまずps4だけ作成
        case "ps4":
            ps4.command(action);
            break;

        //ps4以外のコントロールを追加する場合はここに追記する
        //case "":
            //break;
            
        default:

    }
})

ps4.js

var fnc = require("./functions.js")

//ps4-wakerに関わるアクションをjson形式で用意する
//「止めて」「付けて」「消して」などの命令文の「て」はgooglehomeが勝手に消してしまう模様
const action_list = {
  "起動" : " ",
  "軌道" : " ",
  "付け" : " ",
  "つけ" : " ",
  "停止" : "standby",
  "止め" : "standby",
  "消し" : "standby",
  "消す" : "standby",
  "スタンバイ" : "standby",
  "ホーム": "remote ps",
  "フォーム": "remote ps",
  "メニュー": "remote ps",
  "エンター": "remote enter",
  "センター": "remote enter",
  "選択": "remote enter",
  "バック": "remote back",
  "戻る": "remote back",
  "戻って": "remote back",
  "オプション": "remote options",
  "上": "remote up",
  "笛": "remote up",
  "うえ": "remote up",
  "下": "remote down",
  "した": "remote down",
  "左": "remote left",
  "右": "remote right",
  "メディア": "start CUSA02012",
  "トルネ" : "start CUSA00442",
  "とるね" : "start CUSA00442",
  "default" : " "
}

exports.command = function(action){
  //ここにactionに応じた処理を書いていく

  //「PS4 ◯◯」の◯◯の部分を取得する。
  //IFTTTには「プレステ」で登録しているが、
  //うっかり「プレステ4」と呼んでしまうと「PS4 4 ◯◯」のデータになる
  //この場合にも対応可能にする。
  if(action.split(" ")[1]=="4"){
    //index=1の値が4の場合、うっかりプレステ4と呼んでいるので、index=2の値を使う
    var method = action.split(" ")[2];
  }else{
    //こっちが通常の場合
    var method = action.split(" ")[1];
  }
  //ベースとなるコマンド設定
  var command = "sudo ps4-waker ";
  //上記の〇〇の部分を先頭で定義したjsonから探し、コマンドを取得する
  method = fnc.getJsonData(method, action_list)
  var command = command + method
  console.log(command)

  if(command){
    const exec = require('child_process').exec;
    exec(command);
  }
}

functions.js

//jsonから要素を取り出す関数
exports.getJsonData = function(value, json){
    for (var word in json) if (value == word) return json[word]
    return json["default"]
}

まとめ

無事ps4を操作できる様になりました。
googlehomeからラズパイまでデータを伝えるロジックができたので、
これをベースにして、あとはラズパイのプログラム次第であれこれできそうですね。
そのためにデータベースのactionに入れる値にあえてps4とつけています。

(後日談)
しばらくは順調に機能していたのですが、ある時急に動かなくなってしまいました。
logを見ても正しいコマンドを送れていそうなのに不思議だなーと思っていたら
PS4に使っているLANケーブルが断線していました。
ソフトだけではなくハードも注意しないといけないですね。