# 良くある質問と回答

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

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

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

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

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

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

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

- GPIO

  - 概ね 300ms 以下の周期で細かく High/Low を切り替える必要があるもの（例えばステッピングモータを高速に動かしたいなど）や、概ね 300ms 以上の精度を必要とするも、複数の GPIO 端子を同様な高精度で同期させる必要があるものは困難です。
  - サポートされるポートは P0_0 ～ P0_7 を GPIO 0 ～ 7 番として 8 本のみサポートします。TY51822r3 のその他のピンを GPIO として使用する事はできません。

- I2C
  - 標準モード以外のモードで動作するものはサポートしません。
  - サポートされる I2C バスは 1 本のみです。また MBED の標準とは異なるピンアサインで使用します :
    > P0_29 => SCL
    > P0_30 => SDA

## 動作環境

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

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

- 例えばメールの送信など TY51822r3 に接続されたハードウェアに関わらない機能に関しては純粋に PC 側で走る Web アプリとして実装する事で利用する事ができます。

- Web アプリ側に接続されているハードウェアを動かしたい場合は、通常の Web アプリとして Web USB API や Web MIDI API、またはハードウェア制御のバックエンドのサーバープログラムと WebSocket で通信するなどの方法を取ってください。

## トラブルシューティング

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

制限事項です。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)](https://developer.mozilla.org/ja/docs/Web/Security/Same-origin_policy) というセキュリティ制約があり、JavaScript を読み込んでいるのと異なるドメインの URL には相手側のサーバが [オリジン管理ソース共有 (CORS)](https://developer.mozilla.org/ja/docs/Web/HTTP/HTTP_access_control) で明示的に許可している場合以外は JavaScript のコード中で XMLHttpRequest や fetch からアクセスできません。

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

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

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

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

- 開発者ツールのコンソールに何かエラーメッセージは出ていないですか？
  - 何もエラーが出ないと言っても最初に 1 行だけエラーが出ているケースなどあります。ページをリロードして何もエラーがないか確認してください
- 開発者ツールのネットワークパネルで読み込みできていないファイルはないですか？
  - polyfill や driver などを相対パスで読み込んでいる HTML のディレクトリを移動させた場合、相対パスが変わって必要なファイルが読み込みできなくなっていることがあります
- 配線は本当に正しいですか？
  - 慌てて配線するとピンの配置を 180° 反転させた逆向けで配線していることがあります
- 配線はしっかりしていますか？
  - ジャンパーピンやピンヘッダーの太さが細すぎないか。ブレッドボードに刺す前提で細いピンヘッダを採用しているセンサー (秋月電子の商品など) がありますが、これらをピンソケットに刺すと接触が不安定になることがあります
  - センサー類などの基板にピンヘッダーを付けている場合はそれがしっかり半田付けされているか
- 利用ハードウェアに不良・故障はないか？
  - 不良・故障の可能性のあるハードを順に交換して試してください
  - ソフトウェアと違いハードウェアには配線を間違って使うと不可逆的な損傷を受けて正常動作しなくなるパーツも存在します。壊れたら交換するしかありません
  - サーボモータドライバーなど手作業での半田付けを行うピンヘッダ数が多いパーツなどは半田付けになれている人が作らなければ不良品になることが多く見られます。半田付け直後は動作しても保管している間にダメになるケースもあるので注意してください
  - ジャンパーケーブルのような単純なパーツも安物であれば大容量の電流を流したり曲げを繰り返していると繋がらなくなるケースがあります。ブレッドボードも繰り返し使っているうちにピンの固定が緩く接触不良になることがあります。消耗品は調子が悪くなったら交換してください

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

## デバッグチェックリスト

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

- 開発ツールでのエラーの確認
  - エラーコンソールにエラーメッセージが出力されていないか
    - デバイスにアクセスできないケースにはコードでなく配線に問題がないかも確認する
  - ネットワークパネルでファイル読み込みやアクセスのエラーがないか
- JavaScript コードの確認
  - 該当コードが呼び出されているか
    - 処理が行われない場合、そもそもそのコードが実行されていないことが多いです
    - まずは console.log やブレークポイントで実行されていることを確認します
    - イベントハンドラはイベントの発生前に登録できているか。例えば onload イベントで実行する関数を onload 後に登録するなどしていないか
  - 変数のスコープ (定義域) に問題がないか
    - 別の関数で宣言した変数にアクセスしようとしていないか (コードをコピペなどで移動させたときに特に注意)
  - 実行順序が意図した通りか
    - console.log やブレークポイントで実行順序を確認します
    - 非同期処理の呼び出し時に await を付け忘れていないか確認します
  - 変数には意図した値が代入されているか
    - 様々な原因で意図せぬ値が入っていることがあるため実際の値を console.log やブレークポイントで停止した状態で確認します
    - HTML 要素を取得する場合、要素の読み込みより後で JavaScript を実行しなければ取得できないことに注意してください
- 配線の確認
  - ピンヘッダの何処にどのジャンパーワイヤを刺しているか確認する
  - ピンヘッダに刺す位置を 180° 反転した逆向きに指していないか
  - コードで指定しているピン番号と配線は一致しているか
  - 抵抗などのパーツの配線も正しく行われているか
- 機材の故障
  - LED など内部抵抗の小さいデバイスを抵抗無しで通電するなどすると故障します
  - DC ファンなど極性のあるデバイスは逆指しすると故障します
  - 配線中にショートさせたりするとデバイスもボードも故障します
