Arduinoを USB/HIDデバイス(仮想キーボード)として活用する(第四回）  「radiko(ラジコ)を Arduino から操作する」

##本記事について
　Arduinoを USB/HIDデバイスとして活用する第四回です。[第三回はここ](https://qiita.com/pronechia/items/d44b47b4c9667cea24ac)。前回の予告から方針を変えました（^_^;）。今回は仮想キーボードの実用例として、 radiko(ラジコ)の ON/OFFとチャンネル切り替えを紹介します。
##第四回）「radiko(ラジコ)を Arduino から操作する」
　Arduinoの USB/HID を使って文字列を出力することで、 radiko をON/OFFしたり、チャンネル切り替えをおこないます。操作は Arduinoに設置したSW二つを使って行います。USB/HIDからブラウザーへの上り通信だけで実現しています。下り通信はありません。
##機能概要
 PCのブラウザーにUSB/HID出力することによってradikoを聴くことができます。SW操作で決められた文字列を出力することで radikoを操作することができます。
・Setup処理
　・周辺デバイスを初期化する
　・所定時間後待って、Loop処理に移行
・Loop処理
　・定時間隔毎、処理を繰り返し実施
　・SW１の押下で 指定されたチャンネルのURLをUSB/HID出力し、radikoをONにする。radikoがONの時はOFFにする。
　・SW２の押下で、次回のチャンネルを１つ進める。
##準備するもの
　PC (Windows10) ブラウザーは、Microsoft Edge,Chrome
　Adafruit Trinket M0
　開発環境は  Windows版の Arduino IDE v1.8.9 
##全体の仕組み
 PCはネットに接続できること。Adafruit Trinket M0にはSWが二つありLCDが接続されている。LCDはなくても動くが内部状態がわかりにくい場合がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/560d31e9-9214-f4a3-b221-0ff717be2c51.png)
##ハード構成
 Adafruit Trinket M0 周りのハード構成を示す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/3fc800e4-ec63-69f7-50e9-df2928c8c829.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/aaef4b25-2290-510b-d616-66374892fe44.png)
##ソフトウエア
```ruby:apl_usbhid_TrinketM0_04Wondows.ino
/*
 *公開第四回）radiko操作 2020/06/19
 */
// WindowsPC用
#define USBHOST_WINPC
//環境に合わせて内容を確認または修正すること　ーーここから -----------------------------
//①LCD I2Cアドレスの設定
#define LCDDEVADDR 0x3e
//②ハード設定
#define LED_PIN 13
#define SW_PIN  1
#define SW2_PIN  3
//環境に合わせて内容を確認または修正すること　ーーここまで -----------------------------

#if defined USBHOST_WINPC
String g_url_string = "http'//radiko.jp/#!/live/";
#elif defined USBHOST_MAC
String g_url_string = "radiko.jp/#!/live/";
#else
/設定不備はコンパイルエラーにする
#endif
#define WCS_DELAY_T1 150 //T1 ブラウザー応答時間150
#define WCS_DELAY_GAMEN 3000  //URLたたいてから画面が表示されるまで待つ
#define WCS_SWWAIT_MAXCOUNT 30  //sw押下待ちのリトライ回数上限 30秒
#include <Wire.h>
#include <ZeroTimer.h>
#include "lib_keyboard.h"
#include "LCDManager.h"

int16_t g_pass;  //HID出力したら後の待ち時間を制御する
boolean g_I2CNormal;
boolean g_LED;
boolean g_radio_on;
volatile int g_i; //timerカウント
LCDManager myLCD;
//チャンネル定義は中部地方の例。必要にあわせて変更してください。
int g_channel; //最大3件
char g_annai[3][9] = {"c1:CBC  " , "c2:TOKAI" , "c3:NHK1 "};
char g_radiko_url[3][11] = {"CBC       " , "TOKAIRADIO" , "JOCK      "};
//
//
//
void setup(){
  char w_buf[9];
  g_pass = 1;
  g_i = 0;
  g_LED = false;
  g_radio_on = false;
  g_channel = 0;
  pinMode(LED_PIN,OUTPUT);
  pinMode(SW_PIN, INPUT_PULLUP);
  pinMode(SW2_PIN, INPUT_PULLUP);

  Wire.begin();
  delay(100); //I2Cデバイスの初期化待ち
  //
  if (myLCD.begin(LCDDEVADDR) == false) g_I2CNormal = false;
  else g_I2CNormal = true;
  //
  strcpy(w_buf, " )pushSW");
#if defined USBHOST_WINPC
  sub_kbd_begin(1);  //Windows用に初期化
  w_buf[0] = 'W';
#elif defined USBHOST_MAC
  sub_kbd_begin(2);  //Mac用に初期化
  w_buf[0] = 'M';
#endif
  //
  sub_fw_Blink(LED_PIN, 3, 50); //動き始めたことを知らせる
  delay(100); //HIDデバイスの初期化待ち
  if (g_I2CNormal) myLCD.printStrC1(w_buf);
  if (g_I2CNormal) myLCD.printStrC0(g_annai[g_channel]);
  //
  sub_fw_timerset();  //タイマー起動
}
```
環境に合わせて、以下の内容を確認または修正してください
//①LCD I2Cアドレスの設定
//#define LCDDEVADDR 0x3e
②ハード設定が間違いないか確認
　LED_PIN 13
　SW_PIN  1
　SW2_PIN  3

```ruby:loop処理
//
//main loop
//
void loop(){
  // 20x1=20msec毎に処理を行う
  if (sub_fw_event(1)) sub_proc();
}
//
//USB/HID処理
//
void sub_proc() {
  int j;

  //待ち時間がゼロになるまで何もしない。
  if (g_pass-- >= 0 ) return;

  if (sub_fw_SWcheck(0, SW_PIN) == 2) {
    if (g_radio_on) {
      //Enterを出して止める
      sub_apl_key2();
      if (g_I2CNormal) myLCD.printStrC1("Chan.OFF");
    } else {
      //URL+Tabx3を出す。画面が表示されるまで待つのもこの関数内
      if (g_I2CNormal) myLCD.printStrC1("URL out ");
      sub_initurl();
      sub_apl_key();
      if (g_I2CNormal) myLCD.printStrC1("Chan.ON ");
    }
    g_radio_on = !g_radio_on;
  } else if (sub_fw_SWcheck(1, SW2_PIN) == 2) {
    //channel 切替
    if (g_channel>1) g_channel = 0;
    else g_channel++;
    
    if (g_I2CNormal) myLCD.printStrC0(g_annai[g_channel]);
  } else {
    //その他は何もしない
    ;
  }
  g_pass = 1; 
}
（以下、省略。ソースコードを参照ください）
```
　ソースコードは、[GitHub](https://github.com/pronechia/apl_usbhid_TrinketM0_04)から取り出すことができます。 Windows用とMac用にわかれています。各フォルダー内のすべてのファイルを同一フォルダに保存して、Arduino IDE でコンパイルしてください。
注意）
・LCDのI2Cアドレスが間違った場合は、LCDへの表示をバイパスします。
・ツール／ボードの設定は、 Adafruit Trinket M0 です。
・radiko のチャンネルは中部地方になっています。お住まいの地方に合わせて変更してください。
　設定値：
　　char g_annai[3][9] = {"c1:CBC  " , "c2:TOKAI" , "c3:NHK1 "};
　　char g_radiko_url[3][11] = {"CBC       " , "TOKAIRADIO" , "JOCK      "};
##実行
 準備として、PCがネット接続されていていること。

1.PCと Adafruit Trinket M0 を　USB接続する。SW押下で動き出す。

2.定時間隔で SW１/ SW２待ちを繰り返す。
 2-1.SW2押下で、次のチャンネルに切り替える。チャンネル名はLCDに表示します。
 2-2.SW1押下で、cmd窓を開きURL文字列を入力する。続けて、Tabで再生ボタンまで飛び、Enterで再生（ON)する。
　動作確認中、Tabの数／タイミングがずれた場合や画面表示状態によっては、思ったところで再生ボタンが押せず苦労した。公開されているWebページでは、仮想キーボードの動きは画面デザインに大きく依存してしまい、やりたいことができない可能性もありそうだ。
 2-3.SW１押下で、Enterを押して停止（OFF)する。同時にブラウザーのTabを閉じる。（Chromeの場合のみ）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592438/96157f44-d5d0-2664-ad01-d463a9e7cc28.png)

##まとめ
 仮想キーボードの実用例として、radiko(ラジコ)の ON/OFFとチャンネル切り替えが確認できた。公開されているWebベージを利用する場合は、キーボード操作と画面デザインの依存度が高く、その利用範囲には限界があると感じた。
##参考
Trinket M０の開発環境については、以下を参考にしました。
　https://www.denshi.club/cookbook/arduino/trinketm0/trinket-m01arduino-ide.html
以下のライブラリが必要です。
　・ZeroTimer.h
　　　https://ehbtj.com/electronics/arduino-zero-timer-interrupt-library/