Webチームの蔵下です。Chrome 81でWeb NFCが試験的に導入されました! ちょっと変わり種なのでネット上ではあまり話題にならなかったのですが、個人的にはビッグニュースでした。
Web NFCを使うと、下記のTweetのような実在するカードとWebサイトを組み合わせたゲームなどが実装できます! すごい!
🏷️ Web NFC reaches a key milestone - it is coming soon!
— Chrome for Developers (@ChromiumDev) 2019年12月17日
Check out https://t.co/wC4Sx6Rpu8 pic.twitter.com/MmsIDHGNjy
勢いのままにWeb NFCを触ってみたので、ソースコードを交えて使い方を紹介します。
Web NFCとは?
Web NFCとは、JavaScriptでWebサイトからNFCタグにデータを読み書きできるAPIです。記事公開時点(2020年6月)ではAndroid Chromeでの対応となっているため、NFC機能が搭載されているAndroidスマートフォンで動作が確認できます。
NFCタグ
NFC(Near Field Communication)とは近接型無線通信方式で、デバイスでNFCタグにタッチするだけでデータの読み書きができます。今回Web NFC確認用に Amazon で購入したNFCタグは、容量が144Byteと小さいですが価格も安く手軽に試せます。
Web NFCを試す前の下準備
Web NFCはまだ試験的な導入のため、 chrome://flags/#enable-experimental-web-platform-features
のフラグを Enabled
にするか、 Origin Trials の設置が必要です。
Web NFCのソースコード
Web NFCを実際に試したソースコードを紹介します。
Scan
NFCタグからデータを読み込むには、NDEFReader
の scan()
でScan機能を起動します。起動した状態でデバイスでNFCタグにタッチすると reading
Eventが発火し、NFCタグに付与されているシリアルナンバー( serialNumber
)と書き込まれているデータ( message
)が受け取れます。一度Scanすると、NFCタグにタッチする度にEventが発火します。
const scan = async () => { try { const reader = new NDEFReader() await reader.scan() // Scanは起動しているが、NFCタグからデータが読み込めなかった reader.addEventListener('error', (event) => { console.log(error) }) // データを読み込んだ reader.addEventListener('reading', ({ serialNumber, message }) => { const record = message.records[0] const { data, recordType } = record // recordTypeごとにdecode処理を実行する }) } catch (error) { // Scan起動失敗 console.error(error) } }
受け取った message
の中に、NFCに書き込まれていたデータが records
として配列で格納されています。複数のデータが書き込まれている場合、 records
に複数個の record
が入ります。 record
に付与されている recordType
でデータの種類が特定できるので、recordType
ごとにdecode処理を実装します。
※ 初めて Scan
を実行する際に下記のようなダイアログが表示されます
Text
recordType
が text
の場合はTextデータとなります。 TextDecoder
でdecodeすることで、 data
を文字列として扱えます。
const { data, encoding, recordType } = record if (recordType === 'text') { const textDecoder = new TextDecoder(encoding) const text = textDecoder.decode(data) console.log(`Text: ${text}`) }
JSON
recordType
が mime
、 mediaType
が application/json
の場合はJSONデータとなります。 JSON.parse()
でparseすることで、Objectとして扱えます。
const { data, mediaType, recordType } = record if (recordType === 'mime' && mediaType === 'application/json') { const textDecoder = new TextDecoder() const json = JSON.parse(textDecoder.decode(data)) console.log(json) }
Image
recordType
が mime
、 mediaType
が application/png
の場合はPNGデータ(Image)となります。 data
を Blob
へ変換し、 image.src
に URL.createObjectURL()
で渡すことで画像が表示できます。
const { data, mediaType, recordType } = record if (recordType === 'mime' && mediaType === 'image/png') { const blob = new Blob([data], { type: mediaType }) const image = new Image() image.src = URL.createObjectURL(blob) }
Write
NFCタグへデータを書き込むには、NDEFWriter
の write()
を実行し、デバイスをNFCタグにタッチします。データは文字列で書き込まれるため、データの種類ごとにencode処理が必要になります。
Text
Textは文字列のため、そのまま write()
で書き込みます。
const writeText = async(text) => { try { const writer = new NDEFWriter() await writer.write(text) } catch (error) { console.error(error) } }
JSON
dataは JSON.stringify()
で文字列へ変換し、 recordType
, mediaType
を付与した record
を作成します。作成した record
を records
配列に格納して write()
で書き込みます。
const writeJson = async(data) => { const encoder = new TextEncoder() const jsonRecord = { recordType: 'mime', mediaType: 'application/json', data: encoder.encode(JSON.stringify(data)), } try { const writer = new NDEFWriter() await writer.write({ records: [jsonRecord] }) } catch (error) { console.error(error) } }
Image
書き込みたいImageを ArrayBuffer
へ変換し、 recordType
, mediaType
を付与した record
を作成します。作成した record
を records
配列に格納して write()
で書き込みます。
const writeImage = async (url) => { const imageRecord = { recordType: 'mime', mediaType: 'image/png', data: await (await fetch(url)).arrayBuffer(), } try { const writer = new NDEFWriter() await writer.write({ records: [imageRecord] }) } catch (error) { console.error(error) } }
Imageを書き込む方法は上記のように用意されていますが、NFCタグは一般的に数百バイトと容量が小さく、私達が普段扱っているような画像は書き込めません。今後のNFCタグの性能向上に期待したいですが、しばらくは画像をNFCタグへ直接書き込むことは難しいでしょう。
まとめ
デバイスをタッチしてアクションを起こすという動作は、スマートフォンや交通系ICカードなどの普及もあり、私達の生活で当たり前のものとなりました。今まではネイティブのアプリケーションでしか実装できなかったNFCのデータ通信も、JavaScriptを使ってWebサイトで実装できるようになると、新しいサービスや体験が生まれてくるかもしれません!
今後も変わり種JavaScriptの情報を発信していきますのでご期待ください!
採用情報
アプトポッドでは、一緒に働いてくださる仲間を募集中です。
弊社は、IoT(Internet of Things)という言葉がバズるはるか以前、当時まだM2M(Machine-to-Machine)と呼ばれていたような時代から、IoTミドルウェアやIoTデータの可視化ダッシュボード開発を手掛けてきた、IoTプロダクトのスペシャリスト集団です。(弊社の成り立ちについては、弊社VPoPが投稿しているこちらの記事 アプトポッドの過去と現在、そして未来について - aptpod Tech Blog をご覧ください)
弊社の主力製品は、 IoTプラットフォームの構築用ミドルウェア intdash と、そのミドルウェアを流れる大量のIoTデータを可視化する Webベースのダッシュボード Visual M2M Data Visualizer です。リンク先の弊社サイトでもご紹介している通り、自動車やロボットから収集した秒間数千点にもなるIoTデータを、リアルタイムに遅延なくブラウザ上に描画するパフォーマンスに強みを持っています。
サーバーから WebSocket や WebTransport をベースとした独自プロトコル iSCP(intdash Stream Control Protocol)によってプッシュ型で配信されてくる大量のデータには、数千Hzにもなるセンサーデータだけでなく、映像データや音声データなど、様々なものを含みます。これらをブラウザ上で統合的に可視化することによって、IoTデータの利活用を強力にサポートします。
弊社のWebアプリケーション開発は、大量に送りつけられるデータの捌き方、様々な種類のマルチモーダルデータの取り扱い、独自プロトコルのハンドリングなど、なかなか他では体験できない開発トピックが盛りだくさんです。
情報技術の総合格闘技とも言われるIoTの分野で、我々と一緒に、技術で未来を切り開いてみませんか?
応募は、当社リクルートページよりお願いします。 www.aptpod.co.jp