Technote

by sizuhiko

秋のJavaScript祭りに参加して、Web ComponentsについてLTをしました

11/17に開催されたJavaScript祭りに参加しました

いつもと同様にLT枠へ申し込み、この半年でおきたPolymerのアップデートを発表しました。 とは言いつつ、Polymerのアップデートは少なめで、Chrome Dev Summit で発表された内容を中心に話しました。

今回は、春のイベントで強烈な印象を残したCanvasだけで実装したゲームのLTについて、20分枠で聴けるというのが楽しみでした。 実際20分枠よりももっと聞きたいという感じでしたし、相変わらずすごい。実装も進んでいて、もう1つゲームが公開されていました。

さて、私のスライドは以下のとおりです。

いつもちょうどJavaScript祭りの直前にアナウンスがあるので、発表ネタには困りませんが、最近多忙でなかなか動画を見る時間を作れずギリギリまでスライド内容が決まらなかった….

富士通クラウドテクノロジーさんはUSB-C x HDMIとの相性が悪いのが、以前のPolymerイベントでわかっていたので、事前に運営へお知らせしていたのですが、やっぱりバタバタになってしまっていたのが残念でした。 なんとか改善されると良いなーと思っています。

Polymer.coedo #18を開催しました

今年9回目となる Polymer.co-edo ミートアップ を開催しました。

今回からしばらくは「Edoエレメントの制作とWeb Componentsもくもく」ということで、進めることにしました。

とりあえず以下のオーガナイゼーションを作成して準備を整えました。

  • Edo-Elements - Github
  • edo-elements の npm オーガナイゼーション(これはまだ何もpublishしていないので、リンクにできない….)

イベントに参加いただけたらオーガナイゼーションに招待しようと思うので、よろしくお願いします。

次回は

予定どおり開催できる見込みです。 Doorkeeperのコミュニティページに今年の予定も書いてあるので参考にしてください。

CakePHP2プラグインをTravisCIでビルドしているときに気をつけること

先日 @tenkoma さんが、FabricatePR をくれました。 しかももう枯れてる CakePHP2版 に。ありがたやー、と思っていましたら…

CIのビルドが失敗しています。

おや?直前までは通過していて、READMEのtypoが修正されただけなんですが…

(ただ直前は1年も前なのだが…)

ためしにRebuildしてみる

そういう小手先の問題ではないようだ….

TravisCIに書いてあるスクリプトの手順をローカルで実行してみる

うまく動く…

ビルド失敗の問題とは

失敗ビルドの一例でわかるとおり、PHPUnitのバージョンが期待値ではありません。

CakaPHP2ではPHPUnit3.7系しか使えません。 CakeTestSuiteDispatcherでPHPUnitのロードを試みていて、もしロードできないとTestShellでエラーになります。

CakePHP2のプラグインのテストを簡単に実行できるようにするためFriendsOfCake/travisを使っています。 このTravis用ツールは、PHPUnit3.7をインストールして、 Vendor の下にリンクしてくれるので、うまくPHPUnitは見つかるはずなのですが。

想定される原因としては、以下のような感じです。

  • PHPUnitが見つからない
  • 新しいPHPUnitが見つかった

CakePHPの日本語Slackで相談してみる

https://cakesf.slack.com/archives/C1FT02VQA/p1539927224000100

CakePHP2系のプラグインをTravis CIでテストするのに https://github.com/FriendsOfCake/travis を使っているのですが、PHPUnitへの参照がうまくできなくなっていて、解決した人っていたりしますか? 個人的に修正できそうなんて、試してみようかと思ったのですが、すでに対応済みの人がいたらなーと思い、聞いてみたいです

他のCakePHP2プラグインはビルド通っているのか?

  • https://github.com/lampager/lampager-cakephp2 は5ヶ月ぐらい前に通過している。でもPHPUnitのバージョンが新しい
  • https://github.com/cakephp/debug_kit/tree/2.2 はPHPUnit3.7使っているけど、 FriendsOfCake/travis を使ってない。ビルドは最近通過している
  • https://github.com/tsmsogn/Pas/ は FriendsOfCake/travis を使っていて、Slackで相談したらビルドまでしていただけた。ありがたや。通過している。

とにかくいろいろ試す

試すのに、別のブランチを切れば良かったのですが、まぁ簡単になおるだろうと Fabricate/cakephp2 ブランチで作業したのは、ちょっと後悔しています….

  • FriendsOfCake/travisのbefore_script.sh を呼び出す方法が、 travis_wait 付きに変わっていたので追従した。ビルドが不安定なことがあったが安定した
  • × FriendsOfCake/travis をローカルに fork して、ログを仕込んだりしてビルドを試みた(何も意味はなかった)
  • × FriendsOfCake/travisのbefore_script.shcomposer global install しているPHPUnitを削除して composer require で入れてみた(変化なし)
  • × include_path の先頭にPHPUnitへのパスを設定してみた(変化なし)
  • △ Slackで CAKE_REF 使うと良いかも?というアドバイスをいただいたので、入れてみた。PHPUnitへの参照としては変化がなかったけど、有用そうなのでそのまま採用した。
  • × 既存で composer.json があるのが、FriendsOfCake/travisを使っている他のプラグインと違ったので、 .travis.ymlbefore_script で消してみた(変化なし)

で、TravisCIの画面(のビルド結果コンソールではない部分)を見比べていたら、テストが通過している画面にはワーニングが表示されていて、自分のビルドには出ていないことが判明。 さらに過去に通過していたビルドにもワーニングが表示されていることを確認した。

何のワーニング?

This job ran on our Precise environment, which is in the process of being decommissioned. Please read about the status of the rollout on the blog, and take note that you can explicitly stay on Precise by specifying dist: precise in your .travis.yml.

意訳すると「このビルドは、Precise環境で実行されたけど、廃止予定です。もし続けて使いたければ .travis.yml に dist:precise と書いておけばOK。続きはBlogで」みたいなことです。 the blogも見ておいてください。

precise 指定でビルドしてみる

.travis.ymldist:precise を追加してみると….

ビルドが通過しました!!

ついでに古い composer.lock と composer.json も更新/削除しておきました。

詳しく調べた

現在のTravisでビルドするLinuxイメージは trusty なのですが、そこでPHP5.4などを利用しようとすると以下のようなメッセージがビルドコンソール中に表示されます。

5.4 is not pre-installed; installing Downloading archive: https://s3.amazonaws.com/travis-php-archives/binaries/ubuntu/14.04/x8664/php-5.4.tar.bz2 9.31s$ curl -s -o archive.tar.bz2 $archiveurl && tar xjf archive.tar.bz2 –directory /

ということで、PHPのイメージファイルをダウンロード&解凍してみました。 すると、PHPUnitが同梱されています。 そのバージョンは PHPUnit 4.8.35 でした。 そこかー、それ参照しちゃいましたか…

まとめ

CakePHP2プラグインを作ったことがあって、最近ビルドしていない方は漏れなく同様の事象になると思います。 これはFriendsOfCake/travis使っている、使っていないに関係なくです。

あなたの .travis.ymldist:precise が設定されていなければ、今のうちに追加しておきましょう。

ではステキなCakePHPライフを!

Google Cloud Builder を使って PHP7.2 のアプリケーションを GAE に継続的デプロイする

この記事は、PHPカンファレンス関西2018に参加してGAEに継続的デプロイする方法について発表してきましたの中で紹介しているGoogle Cloud Builderを利用してGAEのPHP SEへ自動デプロイするサンプルコードを最新に更新した解説記事です。

何が変わったのか?

PHPカンファレンス関西2018時点では以下のようになっていました。

  • GAEのPHPは5.5
  • Google Cloud Container Builder を利用

今日では以下のようになっています。

  • GAEのPHPで7.2が利用可能に
  • Cloud Container Builder は Cloud Build という名前に変更

gcloud コマンド利用上での変更

Dockerのバージョンがあがったことで gcloud コマンドから docker コマンドを実行するときに認証設定が必要になりました。 READMEにも反映していますが、以下のコマンドを実行しておく必要があります。

$ gcloud auth configure-docker

gcloud コマンドをアップデートしてみましたが、「PUSH TO DEPLOY のトリガーをセットする」については、まだできませんでした。 projects.builds/create APIは実装されているようなので、CLIから実行できるようになるのを心待ちにしています。

composer イメージの更新

PHP7.2を利用できるようになったので、 composer/composer:php5 のDockerイメージを composer/composer:alpine に変更しました。 composer/composer でも良かったのですが、 alpine ベースの方が軽量だし、いいですよね。

app.yaml の更新

基本的にここがメインなのですが、以下のような変更点があります。

  • runtime を php72 に変更
  • handlersapplication_readable は常に true
  • skip_files でデプロイしないファイルの指定は .gcloudignore ファイルへ移行する
  • / アクセスされたときの script 指定は auto に(ただし index.phppublic/index.php の場合のみで、他はパスを指定)

こういった変更は、Compatibility issues between PHP 5.5 and PHP 7.2にまとめられています。 ※ skip_files については書いていないので、実際にマイグレーションして確認は必要です(これは5.5から7.2の変更というよりは gcloud コマンドのバージョンアップに伴うものだから書いていないのかもしれないです)。

デプロイしてみよう

あとは、用意したコマンドを順番に実行してデプロイ環境を整備してから、 git push するだけで、PHP7.2のアプリケーションがデプロイできます。 githubのリポジトリが Cloud Source Repositories にミラーされるところなどは変わっていませんでした。

さいごに

この内容は プレPHPカンファレンス北海道 で発表する予定だったのですが、地震の影響でイベントが中止となったため、このブログにまとめました。

どこかで機会があれば、GAEとPHP7.2について発表してみたいなと思います。

web-i2cエレメントをより使いやすくしました。

先日のMaker Faire Tokyo 2018 に CHIRIMENコミュニティで参加しましたweb-i2c-element はどうなの? に記述した改良ポイントを使ったchirimen-pianoをアップしました。

変更したポイント:

変更の概要は以下のとおりです。

  • no-web-i2c スロットを指定すると、非対応メッセージを表示できるようになった
  • WebI2cSensorElement を使って、センサー毎の共通実装をなくし、より簡単にセンサーのカスタムエレメントが実装できるようになった
  • Polymer使ってなくても、タグだけを使ってセンサーの値が取得できるようなサンプルに変更した

では、それぞれの変更を詳しく見ていきましょう。

非対応メッセージの表示

chirimen-pianoのリポジトリにあるindex.htmlファイルを見てましょう。

<web-i2c>
  <grove-touch slave-address="0x5a"></grove-touch>
  <grove-gesture slave-address="0x73"></grove-gesture>
  <div slot="no-web-i2c">
    このデバイスはCHIRIMENではありませんが、ピアノ演奏はお楽しみいただけます。
  </div>
</web-i2c>

web-i2c タグの内側に no-web-i2c というslot名のタグを記述することで、 もしCHIRIMEN以外のデバイス(例えばPCなど)から、このページを表示するとメッセージを表示することができるようになります。 試しに、PCからchirimen-pianoのデモページにアクセスしてみてください。

WebI2cSensorElementを利用したカスタムエレメントの記述

最初のバージョンでは、 PolymerElement を使っていたため共通的な実装が多くなっていたのですが、 いくつかのセンサー実装をしてみて共通化できそうな箇所もわかってきたので、I2C用の親クラスを作ることにしました。

WebI2cSensorElement を使ったセンサーのクラスとして、GROVEタッチとGROVEジェスチャーのカスタムエレメントを作りました。

例としてchirimen-pianoのリポジトリにあるgrove-touch.jsファイルを見てましょう。

class GroveTouch extends WebI2cSensorElement {
  async init() {
    this._autoRead = true;
    await this._i2cSlave.write8(0x2b,0x01);
    await this._i2cSlave.write8(0x2c,0x01);
    await this._i2cSlave.write8(0x2d,0x01);
    await this._i2cSlave.write8(0x2e,0x01);
    await this._i2cSlave.write8(0x2f,0x01);
    await this._i2cSlave.write8(0x30,0x01);
    await this._i2cSlave.write8(0x31,0xff);
    await this._i2cSlave.write8(0x32,0x02);
    for(var i=0;i<12*2;i+=2){
      // console.log(i);
      var address = 0x41+i;
      // console.log(address);
      await this._i2cSlave.write8(address,0x0f);
      await this._i2cSlave.write8(address+1,0x0a);
    }
    await this._i2cSlave.write8(0x5d,0x04);
    await this._i2cSlave.write8(0x5e,0x0c);
  }

  async read() {
    const value = await this._i2cSlave.read16(0x00);
    // console.log(value);
    var array = [];
    for(var cnt = 0; cnt < 12; cnt ++){
      array.push(((value & (1 << cnt)) != 0)?true:false);
    }
    if (!this.value || (JSON.stringify(array) != JSON.stringify(this.value))) {
      this._setValue(array);
    }
  }
}

window.customElements.define('grove-touch', GroveTouch);

まず WebI2cSensorElement を継承したクラスを定義します。 このクラスには2つのオーバライド可能なメソッドがあります。

  • init
  • read

どちらも async メソッドにすることで I2Cスレーブデバイスからの応答を待ち合わせる(await)ことができるようになっています。

WebI2cSensorElement は、 init 呼び出し時にメンバー変数として _i2cSlave が利用可能になっています。 これはWeb I2Cのスレーブオブジェクトで、どんなメソッドが使えるかはWeb I2C API Specification4.6 Reading the value4.8 Writing a value を参照ください。 サンプルコードの slaveDevice_i2cSlave と同じものになります。

init を実装する

init ではI2Cデバイスの初期化コードを記述します。 とくに戻り値は必要ありません。

もしセンサーが読み取り可能なら、 this._autoRead = true; のように設定してください。 これを設定すると、インターバル間隔(デフォルトは100ミリ秒)ごとに read メソッドを呼び出してくれます。

read を実装する

init で _autoReadtrue に設定した場合、インターバル間隔ごとに呼び出されます。 センサーの値を読み取って、値が変わった場合は this._setValue(value) を呼び出してください。 エレメントの value プロパティに値が保持されると同時に、 value-changed イベントが発行されます。

普通のHTMLからセンサーを取り扱う

ふたたびchirimen-pianoのリポジトリにあるindex.htmlファイルを見てましょう。

<script>
  document.querySelector('grove-touch').addEventListener('value-changed', e => {
    document.querySelector('chirimen-piano-app').touchChanged(e.detail.value);
  });
  document.querySelector('grove-gesture').addEventListener('value-changed', e => {
    document.querySelector('chirimen-piano-app').gestureChanged(e.detail.value);
  });
</script>

センサー値の変更を受け取るには、センサーエレメントに対して value-changed イベントのリスナーを設定します。 値はイベントオブジェクトの detail.value に入っていて、センサーによってセットされる値(型も含め)が違います。

たとえば grouve-touch エレメントは、タッチセンサーの数分のBoolean配列がセットされ、 grove-gesture エレメントは、発生したジェスチャー名がセットされます。

さいごに

このようにHTMLからセンサーの値をコントロールできたり、センサーのエレメントを簡単に実装できるようになりました。 今後は、それぞれのエレメントやベースクラスを npm install で取得できるようにしたいと思っています。

また、以前作った WebGpioElementPolymer3 で書き換えていきたいなと思っています。

WebComponents と CHIRIMEN の融合は、私がそれぞれのコミュニティに参加して得られたもののアウトプットです。 もしこれらの活動に興味がありましたら、Polymer Japan CHIRIMEN Open Hardware Polymer.co-edo などの活動に参加ください。