良くある質問と回答

CHIRIMEN with ty51822r3 を利用していて良くある質問や回答のメモページです。利用上のテクニックや知っておくと良いことは TIPS ページ に書いているので、そちらも合わせてご覧ください。

できること・できないこと

CHIRIMEN with ty51822r3 では何が出来ますか?

CHIRIMEN with ty51822r3 は一般的な Web アプリケーションの開発環境に、GPIO と I2C という IoT プロトタイピングなどでよく使われるハードウェアインターフェイスを Web GPIO API と WebI2C API を用いてウェブブラウザの JavaScript から直接制御可能にしたものです。

デスクトップ PC などで走らす事ができる Web アプリとハードウェアとのインターフェースは Bluetooth LE (BLE) で接続する、小さな BLE ボード (TY51822r3) で行います。

Web アプリとハードウェアのインターフェースは Web Bluetooth API 上に構築されている専用のプロトコルを経由しますので、インターフェースが準備されている GPIO、I2C 以外の TY51822r3 上のペリフェラル (例えば UART や SPI など) を Web アプリ側から使用する事はできません。

また、GPIO, I2C に対しては以下の制限があります。

動作環境

現在サポートされている BLE ボードは スイッチサイエンス : TY51822r3 のみです。

サービス連携、他のプログラムとの連携等

トラブルシューティング

同時に複数のタブで開くと動作しない

制限事項です。API では特に規定されていませんが排他制御をしており同一のページを複数タブで開くなど、同じポートを同時に扱うコードを書くと正しく動作しなくなることがあります。全てのタブを閉じてから目的のページだけを開き直してください。

コンソールに Uncaught ReferenceError: xxx is not defined などと表示される

変数 xxx にアクセスしようとしているがそれが定義されていないというエラーです。単純に変数名などを Typo (入力し間違え) していることが多いです。次に多いのは定義域の外でアクセスしようとしている場合です。JavaScript の変数スコープは var で宣言した場合は関数単位、let や const で宣言した場合にはブロック単位です。別の関数の中からなど、スコープ外からアクセスしようとしていないか確認してください。

コンソールに Uncaught TypeError: Cannot read property 'xxx' of null や Uncaught TypeError: Cannot read property 'xxx' of undefined などと表示される

オブジェクトのプロパティ xxx にアクセスしようとしている (some.xxx のようなコード)、プロパティ xxx を持つと考えている変数 some がオブジェクトではなく null や undefined となっており、プロパティアクセスができないというエラーです。変数 some の取得・代入をしているコードに問題がないか確認してください。

コンソールに Uncaught (in promise) TypeError: navigator.requestGPIOAccess is not a function などと表示される

関数 (メソッド) 呼び出ししようとしているがその関数が定義されていないというエラーです。この場合 navigator.requestGPIOAccess が関数ではないと言うことですが、polyfill スクリプトを読み込んでいないか、読み込みより前にアクセスしようとしている場合に発生します。

コンソールに Uncaught SyntaxError: await is only valid in async function などと表示される

await 文は async (非同期) 関数の中でのみ利用可能です。関数の中で await を使って非同期処理を行いたい場合、その関数を async 関数として宣言する必要があります。addEventListener など引数に関数を渡している場合に async を付け忘れているケースが多いので注意してください。

// 関数宣言:
async function wait100ms() { await sleep(100); }
// 匿名関数を使う場合:
element.addEventListener("click", async function() { await sleep(100); }, false);
// アロー(矢印)関数を使う場合
element.addEventListener("click", async () => { await sleep(100); }, false);

JavaScript から特定の URL にアクセスできない

コンソールに Failed to load https://...: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://...' is therefore not allowed access. などと表示される

コンソールに Access to fetch at 'https://...' from origin 'https://...' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. などと表示される

CHIRIMEN に限らず一般的な Web 開発でよく見かけるエラーです。Web には 同一オリジンポリシー (Same Origin Policy) というセキュリティ制約があり、JavaScript を読み込んでいるのと異なるドメインの URL には相手側のサーバが オリジン管理ソース共有 (CORS) で明示的に許可している場合以外は JavaScript のコード中で XMLHttpRequest や fetch からアクセスできません。

単純化して言えば、サーバからの HTTP レスポンスヘッダに access-control-allow-origin: * が付与されていれば JavaScript からのアクセスが許可されるため、任意の URL へのアクセスをプロキシ (中継) してレスポンスヘッダを勝手に追加してくれるようなサーバを用意すれば任意のドメインから任意の URL にアクセスが可能になります。

そのような機能を持った公開の CORS プロキシサービスには例えば https://cors-anywhere.herokuapp.com/ や https://cors.io/ などいろいろなものがあります。なお、これらのサービスの利用は本来のセキュリティ機能を無視するものであり、利用に際しては注意が必要です。あくまでもプライバシー情報などを含まないものについて、テストやプロトタイピング時だけに限って利用すべきです。

コードも配線も正しいのにとにかく動作しない!

いろいろな原因が考えらるため、ひとつずつ確認していく必要があります。

ハンズオン・ハッカソン・講義など、講師やチューターなどのいる時は、色々試して分からないときは一人で悩まず遠慮なく質問しましょう。 ひとつのことに悩んで糸口が見つけられないまま何十分も過ごさず、どんどん質問してデバッグテクニックや回避策などを教わってスキルを向上させていってください。

デバッグチェックリスト

問題解決のためのチェックリスト (初心者向け) を書いてみたので参考にしてください: