暮らしの技術

暮らしを豊かにする技術や、特に暮らしを豊かにしない技術があります

新しいパートナーAPIがリリースされました

このクリスマスの日に side_tana の新しいパートナーAPIについてみなさんにアナウンスできることに大変興奮しています!

経緯





問題

パートナーの状態についてAPI経由で取得したいといった要求が急峻に高まっていることが知られています.また,これらのデータは一度デジタルデータにすることができれば,容易に配信可能であることが @tomohi_ro によって指摘されています.

そう,問題はいかに早く現実のステータスを反映するかにあります.

設計

本稿では SORACOM LTE-M Button と AWS IoT 1-Click, AWS Lambda function を用いることであらゆる状況においてステータス更新可能なシステムを実現しました.

f:id:side_tana:20181224003608p:plain

SORACOM LTE-M Button は名前の通り KDDI の LPWA を利用しており全国で使えるため,どういった場所でパートナーと結ばれても即時に状態を反映することが可能です.

デモ

ブツ

Public Read でございます.JavaScript SDKなら以下の感じで動く.

  const config = {
    databaseURL: "https://tana-partner.firebaseio.com",
  };
  firebase.initializeApp(config);
  const database = firebase.database();
  const rootRef = database.ref('/');
  rootRef.on('value', (snapshot) => {
    console.log(snapshot.val());
  });

更新方法

SORACOM LTE-M ボタンは通常のクリック以外に長押しもサポートされているので,今回は長押しを true,通常のクリックをfalse に割り当てました.ということで間違って押しても(あるいは振られても)状態を変えることが可能!便利!

犬さんは絶対にこれ使ってなんか作ってください.

終わりに

SORACOM LTE-M ボタンは標準で1500回の操作か1年間分の利用料が含まれています.つまりこれから1年が過ぎるか,僕が750人のパートナーに恵まれ,そして破局を迎えるその日までとりあえず利用できることになります.果たして出番は来るのか....?

まあとにかくこんな感じでガチャガチャ遊んでたら日付が変わってクリスマスになってしまったワケです.マジかー.メリークリスマス!

f:id:side_tana:20181224005537p:plain

QA

SLAを教えてください

ありません

本当に使われるんですか

知りません

ステータスと現実の状態に差異があった場合に補償はされますか

されません

サポート体制について教えてください

ありません

法人窓口はありますか

ありません

Legacy Partner API のEOLまでのスケジュールを教えてください

私はこれ以前にパートナーAPIをリリースしていませんので、どなたか別の方と勘違いされているのではないでしょうか?

パートナーリクエスAPIのロードマップを教えてください

申し訳ありません、現時点で公開できる情報はありません。

cURL でスプレッドシートにデータを入力する

この記事は adventar.org の23日目に寄せた記事です。

GASでHTTPを受けてスプレッドシートにデータを入力できる、という話を聞いたので試して見た、というような記事です。今回はとりあえず動かしてみて満足することがゴールです。

まず新しいスプレッドシートを作成し、「ツール」から「スクリプトエディタ」を開きます。

次に、スクリプトエディタに以下のようなコードを書きます。リクエストを受けた時刻を一行挿入し、It's works! というテキストを返します。

function doGet(e) {
  var ss = SpreadsheetApp.getActive()
  var sheet = ss.getActiveSheet();
  sheet.appendRow([new Date()]);

  var output = ContentService.createTextOutput("It's works!");
  output.setMimeType(ContentService.MimeType.TEXT);
  return output;
}

続いて、スクリプトエディタのメニューにある「公開」から「ウェブアプリケーションとして導入」を選択します。

f:id:side_tana:20181223010222p:plain

今回は権限について難しいことを考えたくないので、ひとまず全開にします。*1

公開が終わるとURLが発行されるので、cURL で叩いて見ます。

$ curl -L https://script.google.com/macros/s/AKfycbzGf_...(省略)
It's works!%

果たしてスプレッドシートを見てみるとリクエストの時刻が記録されています。

f:id:side_tana:20181223010557p:plain

ということで、めちゃくちゃ簡単にcURLでデータを挿入することができました。POSTでペイロード乗せたりもできるみたいですし、クエリパラメータで指定とかもできるのでは*2 と思います。

記事書くためにやって見たのですが、PC開いてから30分でここまで書き終わっていて本当に手軽だな〜と思います。

はまったところ

スクリプトの更新後にそれを反映するためには、再び「ウェブアプリケーションとして導入」を行う必要があり、かつその際には新しいバージョンを指定する必要があるのですが、これに気がつかず少しハマりました、、、まあきっとドキュメントをちゃんと読めばその辺りフォローされているのでしょう。

そう、今回はなんとドキュメントを読まずにやっています。そういうこともある。逆に言えばとりあえず動かすだけならドキュメンなしでもなんとなくできてしまう、、、なかなかすごいと思います。

明日は id:hitode909 さんいい話が読めるようです。楽しみですね。

*1:本格的な運用を考えるならセキュリティレベルについては考える必要があると思います、また、検証が終わったら「アプリケーションにアクセスできるユーザー」を自分の身にしておくのが良いでしょう...

*2:未確認

どれが最新のファイルかわからなくなったことはないですか? XMPでどれが最新か見分けませんか?

こんにちは.私は id:side_tana.これは ミクシィグループ Advent Calendar 2018 - Qiita 9 日目の記事です.*1

qiita.com

日々を過ごしていると,目の前に複数のファイルがあり,そのどれが最新かわからなくて困る, といった場面に出くわします.皆さんも経験があるのではないでしょうか?

f:id:side_tana:20181209204244p:plain
画像はイメージです

特に雑にファイルをコピーしたり,何らかのサービスやツールを経由してデータをやりとりしているとファイルシステムのタイムスタンプも役に立たず途方にくれることもしばしばだと思います.*2

で,最近 Adobe XMP というファイルにメタデータを付与するための仕様について知る機会があったので,今回は Adobe XMP のデータを元に最新のファイルを見つけてみたいと思います.

なお Adobe XMP と書いているように Adobe が中心となって策定している仕様を利用しますので,全てのファイルで有効な方法ではありません.

PSD ファイルのメタデータを確認してみる

PSD に含まれる XMP メタデータについては,Photoshop で簡単に確認ができます.対象のファイルを Photoshop で開き,ファイルメニューからファイル情報を選択し,開いた画面の左側にあるリストから「Rawデータ」を選択すると,以下のような画面が表示されます.

f:id:side_tana:20181209204731p:plain

これが XMP で表現されたメタデータになります.こうして XMP のデータを眺めているとこんな箇所が出て来ます.

   <xmpMM:History>
    <rdf:Seq>
     <rdf:li
      stEvt:action="created"
      stEvt:instanceID="a8ae5a69-eb77-4089-95e2-f42d2b3de612"
      stEvt:when="2018-08-07T23:37:16.842+09:00"
      stEvt:softwareAgent="XD"/>
     <rdf:li
      stEvt:action="saved"
      stEvt:instanceID="f6d3e01d-15ed-47a9-92a1-2ea2301b2a71"
      stEvt:when="2018-09-23T23:01:14.891+09:00"
      stEvt:softwareAgent="XD"/>
    </rdf:Seq>
   </xmpMM:History>

いかにもそれらしいですね.この xmpMM:History 要素ですが,仕様上は XMP Media Management namespace のプロパティとして以下のように定義されています.

High-level actions that resulted in this resource. It is intended to give human readers a description of the steps taken to make the changes from the previous version to this one. The list should be at an abstract level; it is not intended to be an exhaustive keystroke or other detailed history. The description should be sufficient for metadata management, as well as for workflow enhancement.

ファイルの更新履歴のようなので,これで最新のファイルを発見できそうです.

PSD ファイルから XMP メタデータを取り出してみる

XMPメタデータを読み取るために,我々*3はまず PSD のヘッダフォーマットについて理解する必要があります.

PSD ファイルは8BPS から始まる26バイトのヘッダブロックを持ちます.次に可変長のカラーモードデータを持ち,そのあとにイメージリソースが続きます.イメージリソースには複数のブロックが含まれ,各ブロックは8BIMから始まり,2バイトのイメージリソースID,可変長の name フィールド,4バイトのイメージリソースデータのバイト長,実際のイメージリソースデータ,と続きます.

また,XMPメタデータはイメージリソースブロックに含まれ,イメージリソースID は 1060,nameフィールドは 2バイトの null であることがドキュメントで示されています.これらの情報を元に実装すると,<?xpacket?> で囲まれた xml ドキュメントを取り出すことができます. *4

f:id:side_tana:20181209210045p:plain
man ascii は便利 #宣言的知識

こうして xmp メタデータを取り出すことができればあとはこっちのものです.実際に複数の PSD ファイルの履歴をまとめて表示するページを用意しました*5.どうぞお手元の PSD ファイルをドラッグ&ドロップで読み込ませて見てください.(全ての処理はブラウザ上で完結しているので,外部への送信などはしていません.)

XmpMmHistoryViewer


f:id:side_tana:20181209215250g:plain

こうして メタデータから最新の編集時刻を見つけ出し,最新版を見つけ出すことができました.*6

おわりに

今回は XMP メタデータについて紹介し、実際にその一部である XMP Media Management namespace に含まれる ResourceEvent を利用してみました。XMP には他にもキャンバスサイズやサムネイル、使用しているフォントリストなど、使いがいのあるデータが色々と埋まっています。一方で,XMP は必ずこのデータを含む,と言った制約はほぼないため,欲しいデータが含まれているかどうかは実際に手を動かして見ないとわからないのが難しいところですね.

ぜひ年末のファイルシステムの大掃除に役立てたり、正月休みの空いた時間に身の回りをファイルを手にとってメタデータを取り出してみたりして楽しんでください。

*1:昨日の記事は @manji602 さんで ユーザにやさしいサービスを作るための3つのポイント - 問い合わせはサービス改善への近道 - - Qiitaでした.

*2:と書いておいてなんですが筆者はここしばらくソースコード以外のデータを触る業務から離れているためこう言った経験はめっきり減りました.と思ったけど Google Spreadsheet が野放図に複製されてどれが最新かわからなくなる地獄みたいなのあったな,あれまじでどうにかなりませんか,本当に困っています.

*3:我々

*4:実際のところ,あるファイルから XMP メタデータを取り出す方法というのは大きな問題です.XMP メタデータはファイル形式が変わっても引き継がれる場合があるため,事前にファイル形式を定められないケースがあるためです.具体的には Photoshop で作成した画像を jpeg として書き出した際にメタデータが引き継がれる,と言ったようなケースです.基本的なアプローチとしては今回のようにファイル形式に関する前提知識を利用して取り出すことが推奨されています.xpacket マーカを頼りに探索的に取り出すことアプローチもありますが,不確実性が高く壊れやすいロジックのため推奨されていません.

*5:動作についてはAdobe Photoshop CC 2019 で作成された PSD ファイルでのみ正しく動作することを確認してます.偶然手元にあった Adobe Photoshop CS5 Macintosh で作られたやつはダメだった.2019 では単一の要素にまとめられてた箇所か とっ散らかってた.

*6:本当は編集ツリーみたいなのまで作ろうと思ったのですが,どうやらイベントが新規に記録されるタイミングと更新されるタイミングがあるらしく,意図通りに保存記録を積み上げたデータが作れなかったので断念したという背景があります

ショートカットアプリで遊んだらすごかった

こういうツイートを見て,こうしちゃおれんと思って帰宅してすぐインストールした.

しばらくいじっていると色々できそうなことがわかったので,取り急ぎ雨雲ズームレーダーのスクリーンショットをとって HTTP で外部に送り出すショートカットを作った.

f:id:side_tana:20180921005243j:plain

ここからインストールできるっぽい? 雨雲ズームレーダー

全体像はこんな感じです.

f:id:side_tana:20180921011149p:plain

最後のアクションがLAN内にアップローダがいることを期待するのでそのままでは動かないと思います.アップローダはとりあえず動けばいいかってことで go で雑に書いた .適当に置いて go run uploader.go していただいて,アップローダの ip アドレスを正しく指定するとこんな感じの画像が入るはず.

f:id:side_tana:20180921010320p:plain

入力と出力の型がよくわかんなくて最初戸惑ったけど,慣れてくると結構簡単? って感じで,めちゃくちゃ簡単にプログラム作れて感動した.Siri から簡単に呼び出せるのもいいし,↑みたいな感じで簡単に公開用 URL を作れるのもいい.

バージョン管理できないとか,任意のDOMを選択,みたいな高度なことはできないっぽいけど,なんかパネルを並べていくだけで動くものができるのはすごい.未来のプログラミング体験だと思う.

GAE/SE Node で puppeteer を動かすよ

みなさん puppeteerつかってますか? 私は使ってません。なぜなら安定的に稼働させるための環境がないから...*1

しかしそれも今日までです。

先日 beta になった GAE/SE Node について

という話を聞きました。聞いたからにはやります。以下の通り。

const puppeteer = require('puppeteer')
async function takeScreenShot(url, filePath) {
  const browser = await puppeteer.launch({args: ['--no-sandbox']});
  const page = await browser.newPage();
  await page.setViewport({
    width: 1024,
    height: 768
  });
  await page.goto(url);
  await page.screenshot({
    path: filePath
  });

  await browser.close();
  return
}

こんな感じの関数を定義して動かした。ブログ用にちょっと整形したので、なんらかのミスで動かないかも。

以下感想と解説です。

起動時に --no-sandbox オプションがいる

コンテナ環境下で Chromium を動作させる場合に --no-sandbox オプションを要求されるの知らなくて最初うごかせなかった。ちゃんとエラーメッセージには書いてあるので、あとはどうやって puppeteer 経由で起動オプション渡すかって話だけど、上のコードみたいに .launch() に渡すオプションに args キーの値として渡せばいいらしい。

--no-sandbox オプションについてはちゃんと調べられてない。システムコール周りの話なのかなと思ってるけどなんなんだろうか……

インスタンスサイズ

デフォルトのインスタンスだとメモリ不足になったので、大きめのインスタンスを使っている。具体的には F4 インスタンス

f:id:side_tana:20180625225037p:plain

めちゃくちゃシンプルなページでも標準の F1 や F2 ぐらいだとこんな感じでメモリ不足に陥る。

上のスニペットで最後に毎回 browser.close() してるのはメモリ問題への対策なのだけれど、これでも連続して重めのページをレンダリングすると死んでしまう。あんまり死ぬようなら F4_1G にあげるしかか無いけど、その辺は様子見ながらやっていこうと思う。

その他

実際には 1 週間のライフサイクルを設定した GCS バケットスクリーンショットをアップロードし、 Slack に投稿している。 Slack に投稿するところ久々にやったので、画像の展開方法わかんなくてちょっと大変だった。( attachments.[].image_url が必要なやつ)

f:id:side_tana:20180625225847p:plain 要所を黒塗りにしたら訳がわからなくなりました

反省

開発環境あんまり整えずにガーッと書いたので、ローカルで何も考えずに動かすと GCS にアップロードできずに落ちたり、flowtype も無く typescript で書いているわけでも無いので後半めちゃくちゃ辛くなってしまった。

最近は会社も家も静的型付け言語 + IDEの静的解析とか、flowtype みたいなスタティックタイプチェッカの支援を受け続けてるし、テストもだいたい書いているのであまり苦がなかったのですが、久々にこう、大変な感じでしたね、、、。

*1:まあ別に転がしてる VPS とかラズパイとかあるんですけど、Slack の slash コマンドと組み合わせたいな〜とか考えるといい感じの環境ないな〜っという意味です