Wio LTE 体験会にいってきました

Wio LTE 体験会にいってきました

f:id:ueponx:20171105122920j:plain

先日、連休中に行われたWio LTE 体験会にいってきました。

seeed.connpass.com

ここ最近Seeedさんによく行っているような気がします。

Wio LTEについては

soracom.jp github.com

このあたりをみていただくとして、LTEの通信とGroveのセンサーが使えてArduino IDEでプロトタイピングできるIOボードって感じでしょうか。(間違っていたらごめんなさい)

最近は、Arduino IDEの環境で開発するボードが増えてきているので、比較的とっつきやすいかなと思います。

環境設定

まずはパッケージを開けてアンテナコネクタにケーブルを接続し、続いてSIMカードを指します。SIMコネクタの部分に関しては2階建て構造になっているので下側(基板側)にコネクタ面を基板側の向きで差込ます。

このあたりはSORACOMの松下さんのブログが詳しく書いてあります。

blog.soracom.jp

接続が終わると以下のような感じになります。

f:id:ueponx:20171105122844j:plain

ここまでできたら後はソフトウエアの環境設定になりますが基本的にはこちらの情報を元に設定していけばLチカまではいけるかなと思います。

github.com

自分はArduino IDEは既にインストールしていたので以下の手順を踏んでいきました。

  • Wio Tracker LTEボードの追加
  • Wio LTEライブラリの追加
  • DFUモード起動時のWinUSBデバイスドライバーに切り替え
  • 通常モード起動時のVirtual COM Portデバイスドライバーのインストール*1

    この4つを行いました。

    自分は通常モード起動時のドライバーの認識では手順にはない認識状態になりました。とりあえずそのまま作業を行い初回の書き込みまではうまく行ったのですが、その後シリアルモニタが開けなかったので、この状態でもVirtual COM Portデバイスドライバーのインストールを行った方がいいかと思います。

    USBシリアルデバイスとして認識されている f:id:ueponx:20171105115958j:plain

    初回の書き込み後、シリアルデバイスの認識が以下に変化しました。 f:id:ueponx:20171105120016j:plain

    インストール後は【STMicroelectronics Virtual COM Port】に変化してシリアルモニタで確認できるようになります。

    f:id:ueponx:20171105122824j:plain

    SampleのフルカラーLEDのLチカも動作しました。

    Groveセンサーの接続(温湿度センサー)

    続いてはGrove接続のセンサーである温湿度センサーを接続してみます。

    Grove - Temperature&Humidity Sensor - Seeed Wiki

    多分これだと思います。

    こちらサンプル例のスケッチから

    f:id:ueponx:20171105124703j:plain

    上記のように操作してgrove-temperature-and-humidity-sensorを選択します。

    センサーはソースにも書いてある様に【D38】に接続をします。

    【抜粋】

    #include <WioLTEforArduino.h>
    
    #define SENSOR_PIN    (WIOLTE_D38)
    
    void setup()
    {
      TemperatureAndHumidityBegin(SENSOR_PIN);
    }
    …(以下略)…
    

    続いて書き込みになります。書き込み時にはボードをDFUモードにするのを忘れないでください。DFUモードと通常モードの違いはデバイスマネージャを確認するか、Arduino IDEで【ツール】→【シリアルポート】の部分がグレーアウトしているかを見てもわかるかなと思います。(…後者は多分)

    書き込みは問題ないと思いますので、正常に終了したらリセットボタンを押して通常モードで起動します。そして、シリアルモニターを起動すると以下のような画面になると思います。

    f:id:ueponx:20171105120051j:plain

    これで温度と湿度が取得できました。

    LTEで通信(IFTTTで通知する)

    先程まででセンサーの値が取得できたので、次はLTEを使った通信になります。 IFTTTのWebhooksを使用してデータを送信し、送信後PushBulletを使ってプッシュ通知を行います。

    ifttt.com

    Pushbullet - Your devices working better together

    Pushbulletはスマートフォンのアプリでもありますが、Chrome拡張もあります。 f:id:ueponx:20171105131254p:plain

    ハードの接続はこれまでの手順で終わっていますので、特に作業はありません。

    こちらもサンプルを使用しますが、そのままではダメなのでベースにして作業を行います。

    IFTTTの設定

    IFTTTに登録する新しいアプリを作成します。(事前にPushBulletのサービスへログインしておいてください。

    f:id:ueponx:20171105132645j:plain

    IFTTTにログインして画面右上の下向き矢印をクリックし、【New Applet】を選択します。ここからアプリの設定が開始になります。

    f:id:ueponx:20171105132813p:plain

    画面の【[+]This】のボタンをクリックします。するとトリガーとなるサービスの選択画面に遷移します。

    f:id:ueponx:20171105133042p:plain

    今回は検索ボックスにWebhooks(旧MakerChannel)を入力します。

    f:id:ueponx:20171105133312p:plain

    すると、サービスが一つに絞られます。このWebhooksのアイコンをクリックします。

    f:id:ueponx:20171105133437p:plain

    つづいでトリガーの選択になりますが、ここは一つしかないので【Receive a web request】を選択します。

    f:id:ueponx:20171105134305p:plain

    トリガーに名前を付けます。これをプログラムでも使用するのでメモします。自分はwiolte_sampleと名前を付けました。名前が決まったら【Create trigger】のボタンをクリックします。

    f:id:ueponx:20171105140045p:plain

    次にトリガーに対する動作の設定になります。トリガーの設定同様に【[+]That】をクリックすると、サービス選択画面になります。

    f:id:ueponx:20171105140501p:plain

    検索ボックスにpushbulletを入力すると、サービスが絞り込まれますので、PushBulletのアイコンをクリックします。

    f:id:ueponx:20171105140710p:plain

    Pushbulletにはサービスが4つありますが、今回はPush a noteを使用します。アイコンというかボタンをクリックします。

    f:id:ueponx:20171105142719p:plain

    あとは細かい設定ですが、今回は通信ができたことが知りたいので、そのままにして【Create action】のボタンをクリックします。

    f:id:ueponx:20171105143633p:plain

    最後の確認画面になるので、【Finish】ボタンをクリックします。

    f:id:ueponx:20171105144141p:plain

    これで一応IFTTT側の設定はおわりなのですが、WebhooksのKeyも必要になるのでそれを取得しておきます。(自分はここで毎回悩みます) 画面内の左上のWebhooksの文字をクリックします。

    f:id:ueponx:20171105144555p:plain

    するとWebhooksのサービス画面になります。

    f:id:ueponx:20171105145116p:plain

    画面内の【Documentation】のボタンをクリックします。

    f:id:ueponx:20171105173715p:plain

    するとキーが表示されるのでこれもメモしておきます。

    コードの改良

    忘れずに冒頭のWEBHOOK_EVENTNAMEWEBHOOK_KEYを自分の作成したものに変更します。

    【ifttt-webhookのサンプル例-抜粋】

    #include <WioLTEforArduino.h>
    #include <stdio.h>
    
    #define APN               "soracom.io"
    #define USERNAME          "sora"
    #define PASSWORD          "sora"
    
    #define WEBHOOK_EVENTNAME "wiolte_sample" //メモしたものに変更
    #define WEBHOOK_KEY       "XXXXXXXXXXXXXXXXXXXXXXXXXXXX" //メモしたものに変更
    #define WEBHOOK_URL       "https://maker.ifttt.com/trigger/"WEBHOOK_EVENTNAME"/with/key/"WEBHOOK_KEY
    
    …(以下略)…
    

    オリジナルのサンプルでは、起動してからの起動時間を表示するものなので、これをGroveセンサーで取得した温度と湿度に変更します。 先程のgrove-temperature-and-humidity-sensorサンプルとifttt-webhookサンプルをあわせたものになります。

    【ifttt-webhook-改】

    #include <WioLTEforArduino.h>
    #include <stdio.h>
    
    #define APN               "soracom.io"
    #define USERNAME          "sora"
    #define PASSWORD          "sora"
    
    #define WEBHOOK_EVENTNAME "wiolte_sample" //メモしたものに変更
    #define WEBHOOK_KEY       "XXXXXXXXXXXXXXXXXXXXXXXXXXXX" //メモしたものに変更
    #define WEBHOOK_URL       "https://maker.ifttt.com/trigger/"WEBHOOK_EVENTNAME"/with/key/"WEBHOOK_KEY
    
    #define INTERVAL          (60000)
    
    #define SENSOR_PIN    (WIOLTE_D38)
    
    WioLTE Wio;
    
    void setup() {
      delay(200);
    
      SerialUSB.println("");
      SerialUSB.println("--- START ---------------------------------------------------");
    
      SerialUSB.println("### I/O Initialize.");
      Wio.Init();
    
      SerialUSB.println("### Power supply ON.");
      Wio.PowerSupplyLTE(true);
      delay(5000);
    
      SerialUSB.println("### Turn on or reset.");
      if (!Wio.TurnOnOrReset()) {
        SerialUSB.println("### ERROR! ###");
        return;
      }
    
      SerialUSB.println("### Connecting to \""APN"\".");
      delay(5000);
      if (!Wio.Activate(APN, USERNAME, PASSWORD)) {
        SerialUSB.println("### ERROR! ###");
        return;
      }
      
      SerialUSB.println("### init Sensor.");  
      TemperatureAndHumidityBegin(SENSOR_PIN);
    }
    
    void loop() {
      char data[100];
      int status;
    
      float temp;
      float humi;
    
      if (!TemperatureAndHumidityRead(&temp, &humi)) {
        SerialUSB.println("ERROR!");
        goto err;
      }
      SerialUSB.print("Current humdity = ");
      SerialUSB.print(humi);
      SerialUSB.print("%  ");
      SerialUSB.print("temperature = ");
      SerialUSB.print(temp);
      SerialUSB.println("C");
    
      SerialUSB.println("### Post.");
      sprintf(data, "{\"value1\":\"temp %f\", \"value2\":\"humi %f\"}", temp, humi);
      SerialUSB.print("Post:");
      SerialUSB.print(data);
      SerialUSB.println("");
      if (!Wio.HttpPost(WEBHOOK_URL, data, &status)) {
        SerialUSB.println("### ERROR! ###");
        goto err;
      }
      SerialUSB.print("Status:");
      SerialUSB.println(status);
    
    err:
      SerialUSB.println("### Wait.");
      delay(INTERVAL);
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////
    //
    
    int TemperatureAndHumidityPin;
    
    void TemperatureAndHumidityBegin(int pin)
    {
      TemperatureAndHumidityPin = pin;
      DHT11Init(TemperatureAndHumidityPin);
    }
    
    bool TemperatureAndHumidityRead(float* temperature, float* humidity)
    {
      byte data[5];
      
      DHT11Start(TemperatureAndHumidityPin);
      for (int i = 0; i < 5; i++) data[i] = DHT11ReadByte(TemperatureAndHumidityPin);
      DHT11Finish(TemperatureAndHumidityPin);
      
      if(!DHT11Check(data, sizeof (data))) return false;
      if (data[1] >= 10) return false;
      if (data[3] >= 10) return false;
    
      *humidity = (float)data[0] + (float)data[1] / 10.0f;
      *temperature = (float)data[2] + (float)data[3] / 10.0f;
    
      return true;
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////
    //
    
    void DHT11Init(int pin)
    {
      digitalWrite(pin, HIGH);
      pinMode(pin, OUTPUT);
    }
    
    void DHT11Start(int pin)
    {
      // Host the start of signal
      digitalWrite(pin, LOW);
      delay(18);
      
      // Pulled up to wait for
      pinMode(pin, INPUT);
      while (!digitalRead(pin)) ;
      
      // Response signal
      while (digitalRead(pin)) ;
      
      // Pulled ready to output
      while (!digitalRead(pin)) ;
    }
    
    byte DHT11ReadByte(int pin)
    {
      byte data = 0;
      
      for (int i = 0; i < 8; i++) {
        while (digitalRead(pin)) ;
    
        while (!digitalRead(pin)) ;
        unsigned long start = micros();
    
        while (digitalRead(pin)) ;
        unsigned long finish = micros();
    
        if ((unsigned long)(finish - start) > 50) data |= 1 << (7 - i);
      }
      
      return data;
    }
    
    void DHT11Finish(int pin)
    {
      // Releases the bus
      while (!digitalRead(pin)) ;
      digitalWrite(pin, HIGH);
      pinMode(pin, OUTPUT);
    }
    
    bool DHT11Check(const byte* data, int dataSize)
    {
      if (dataSize != 5) return false;
    
      byte sum = 0;
      for (int i = 0; i < dataSize - 1; i++) {
        sum += data[i];
      }
    
      return data[dataSize - 1] == sum;
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////
    

    編集が終了したら書き込みです。何回もいいますが、書き込み時にはボードをDFUモードにするのを忘れないでください。 書き込みが終わったらリセットして通常モードで起動します。

    f:id:ueponx:20171105150404j:plain

    動作させるとシリアルモニター側に接続の様子と温度湿度の様子が表示され、定期的にPushBulletから通知がトースト表示されるようになります。

    おわりに

    Wio LTEを使ってセンサー情報をつかったプッシュ通知ができました。ここまででだいたい2時間ぐらいかなと思います。 (IFTTTの設定で手こずらなければもっと早くできたかなと思いますが。)サンプルも充実し、使いやすいので かなり注目のデバイスです。 この後にはSORACOM Harvestにもアップロードする実験をしたのですが、それについては別エントリーで書こうかなと思います。こっちもサンプルのソースを改良するだけでうまく行きますよ。

    購入するのであれば、センサーセットが12月に発売されるのでそっちがいいかなと思います。

    soracom.jp

    Seeedの坪井さん、松岡さん、参加者のみなさん、どうもありがとうございました。

    次回も開催されるようなので興味のあるかたは参加してはどうでしょうか?

    seeed.connpass.com

    *1:ドライバーの取得は申請しないと行けないのでこの部分だけかなり時間がかかります。 公式のWikiが変更されましたので短縮されたと思います。 InstallVCOMDriver ja · SeeedJP/WioLTEforArduino Wiki · GitHub

Nagoya Hackathonに参加してきました

Nagoya Hackathonに参加してきました

10/28~29に開催されたNagoya Hackathonに参加してきました。

jellyware.jp

  • テーマ:「女性や外国人に愛される街となるIoT製品やサービスを創り出せ!」
  • 開催日時:平成29年10月28日(土)〜10月29日(日)
  • 開催場所:「星ケ丘ボウル」会議室

会場がボーリング場・・・?なんとなく不思議な感じ。 また、女性や外国人というキーワード。そういうこととは無縁の駄目社会人なので一抹の不安はありますが 参加資格をみると「法人または個人のクリエイター/エンジニア/プランナー」ということだったのでダメ元で 参加申し込みをしてみました。

申込者多数ということもあって参加者は抽選だと連絡をもらっていたので、ハッカソン本戦は参加できない 可能性もあるなとあったので前週にあったプレイベントに参加することにしました。 でっかい台風が近づいていましたが、このハッカソンでは今まで参加したハッカソンにはなかった 素材系の提供(紙や印鑑?)があったのでそのあたりを確認したくてのプレイベント参加でした。

f:id:ueponx:20171101100800j:plain f:id:ueponx:20171101100832j:plain

Seeedの松岡さんも提供社側としての参加で来ていました。

気になっていたのはストーンペーパーとワーロンシート。ハッカソンではIOTっぽいものとか、Webサービスを作ることが ほとんどだったので、今回のハッカソンではこういう素材を是非使ってみたいなあと思っていました。 ただ、この時点ではアイデアは全く浮かばず…なんとなく女性よりも外国人向けというキーワードのほうがありかなーという程度でした。

株式会社ミツモリ

株式会社ワーロン

プレイベントが終わり連絡がなさそうなので、今回のハッカソンは発表だけでも見学に行こうかな~と 思っていると参加通知のメールが。正直なところ名古屋市さんの考え方からするとオープン・イノベーションで 事業継続を目指すような企業の方々の参加がメインターゲットだろうな~と思っていたので正直参加できたのは驚きもありました。 (クジ運を大きく使ってしまった感あり)

一日目

台風が2週続けて近づくという10月ではほとんどありえない天気でしたが、気合をいれて行きました。 会場の星ヶ丘には名古屋に来てからまだ数回しか来たことがなかったので、地下鉄で東山公園に間違えて降りてしまったというプチ失敗もありましたが なんとか会場に到着(星ヶ丘テラスができてからは一回ぐらいしか来たことないかも?)

f:id:ueponx:20171101100951j:plain

会場につくとまさにボーリング場。星ケ丘ボウルにはパーティールームがあるのは知っていたのですが、こんなにおおきいとは予想以上です。

f:id:ueponx:20171101101447j:plain

配布資料↓

f:id:ueponx:20171101101512j:plain

f:id:ueponx:20171101101523j:plain

今回、IOTぽいものを作るつもりだったので、手持ちのArduino UNO R3、NefryBT、FlashAir、抵抗セット、ワイヤーを持っていきました。 RaspberryPiを持っていかなかったのはちょっと失敗。会場にはSeeedさんのGrove関連のボードとセンサーやハンダゴテなどの工具一式が あったのでそこまで準備しなくてもよかったようです。カッター、はさみ、物差し関係は忘れていたのでかなり助かりました。あとレーザー加工機も運び込まれていたのでかなり事前の準備が大変だったのだろうなと思います。

f:id:ueponx:20171101101945j:plain

最初に名古屋市さんから名古屋市の状況とハッカソンに関しての説明があり、そこからアイデアソンを開始となります。

f:id:ueponx:20171101101732j:plain

f:id:ueponx:20171101101741j:plain

イデアソン中にKさんが激励に来たのは少し驚きました。

f:id:ueponx:20171101101823j:plain

テレビの取材もありました。さすが名古屋市が主催だといつものハッカソンとはかなり変わりますね。

f:id:ueponx:20171101102335j:plain

アイスブレイクからアイデア発散をしてチームビルディングへいろいろあったのですが、結局テーマとはあまりかけ離れたアイデアに収まってしまいました。

f:id:ueponx:20171101102702j:plain

徳川園で日本刀をつかったウエディングケーキ入刀のイベントがあると聞いたことがあったので、それを更に発展させて、刀を抜いて勇者っぽく演出できないかなと思いました。聖剣伝説2とかアーサー王エクスカリバーとかゼルダの伝説スカイウォードソードとかみたいな感じで気分が上がるかなと。これを何かのアイデアの一部分に取り入れたいという感じだったので、これだけでは成立は難しいかなとは感じていました。

そして、それぞれのアイデアをつかってのチームビルディングを開始。みんなのアイデアを机に置いて良いと思ったアイデアに印をつけていきます。 自分のアイデアは8個でした。

f:id:ueponx:20171101103420j:plain

自分はすごろく形式で観光名所をめぐるアイデアのチームにジョインしました!チームに本職のデザイナーの方がいたのはほぼ初めてだったんですが、ほんの数分で下のような絵がかけていたので本職スゲーと思っていました。

f:id:ueponx:20171101103757j:plain

今回のアイデアのポイントは「巻物」になります。この巻物をキーにして観光地に仕掛けられたミッションをクリアしていくアイデアになります。最近はデジタルなもののサイクルが早すぎて、陳腐化や保存などが難しい状況にあります、そこでこのようなアナログ的なものを外国人旅行者に持って帰ってもらい、ここでしか体験のできないようなこと、そしてモノとして巻物をお土産として持って帰ってもらうことで特別なものを得てもらおうというアイデアとなります。この巻物は素材提供のあったストーンペーパーとワーロンシートを使って作成します。IoT的な要素がない…ですが、スマホでかざして国際化なども検討していました。

ストーンペーパーへの柄選んで印刷をお願いしました。柄のない紙でも巻物を作成してみましたが、ストーンペーパーの手触りがなんともいえずいい感じです。しっとりとした感じがいいようです。巻物も外で使用することを考えていたので、水にも強いというのが利点といえます。

1日目の最後に大々的なピボットで方針変更!ここからが大変でした。

やはりIOT的な要素をいれるということで、体験イベントのスポットに近づくと巻物を光らせようということで話が少し方向修正しました。これでIOTぽさがアップ。

巻物に入れるのはこちらのビーコンになります。

mamorio.jp

BLEなビーコンです。SDKiPhoneAndroidの2タイプ。この時点ではどちらの開発環境もなし。これが大変な変更になるとは…

1日目終了

会場は24時まで使用可ということでしたが、さすがに終電が厳しいので22:00ぐらいに解散。

家に帰ってからMAMORIOさんを使ったプログラミング。MAMORIOさんはiBeaconデバイスということがわかったので、iBeaconの受信検知のプログラムをRaspberryPiで作成する方向にしました。(Windows10でもいいんだけど、情報がすくなそうなので今回はRaspberryPiです)

BLEでのドライバなどインストールをしていたところ、Bluezのドライバーが認識できず。さすがに作業中だったのでこれから復旧をするのはやばい状況だったので、クリーンインストールを行いました。

RaspberryPiのイメージも手元になかったので、最新のRaspbianのダウンロード、クリーンインストール、Node.jsのインストール、Bluezの設定と進み、26時頃からやっとコーディングができるようになり、MAMORIOのUUIDなどの情報をえることができ、Lチカまでなんとかたどり着きました。

意外と誤差はあるようですが、本来は距離情報としてnearとfar程度がわかれば良いので大丈夫そうです。LEDは状態がnearになったら点灯するような感じです。

f:id:ueponx:20171101125312p:plain

この時点で28時、さすがに眠さマックスになったのでここで就寝。初めてレッドブルの効果を体感したような気がしました。(本当に目が覚めるもんなんですね。)

2日目

泣いても笑っても最終日です。まあ笑いますけどね。

ここまででビーコンに近づくとLチカするところまではできているのでもう少し派手に光らせたいと思いました。Seeedさんの持ち込み機材にLEDテープがあったのでそれを使用させてもらうことにしました。2日目にはGrovePiを持参していたのですが、SampleなどがなさそうだったのでWio Node経由で制御することにしました。

自分もWioNodeは持っていたのですが、WioNodeを使うと接続した機器をREST APIでアクセスできるという機能があるのは初めて知りました。今後もこれは結構使えるかも!

LEDテープはこちらについているセットのものかな?

そして、これらをあわせて制御してプロトタイプができました。ビーコンのproximityがnearでLEDテープが白色に点灯、immediateになったらピンク色に点灯するように設定しています。

f:id:ueponx:20171101121505j:plain

電源はUSBバッテリーです。

午後になるとストーンペーパーの印刷も出来上がったので「巻物」もいよいよ完成です。

f:id:ueponx:20171101122029j:plain

筒の中にMAMORIOとLEDテープとWIO NODEを入れる感じです。電源は入らなかったので外だしです。アイデアの発案者のもりちゃんも満足の様子です。

f:id:ueponx:20171101122420j:plain

各チームとも準備ができて、プレゼンの練習に入っているようでした。

f:id:ueponx:20171101122606j:plain

巻物もいよいよ準備完了!後は発表です。

f:id:ueponx:20171101123522j:plain

f:id:ueponx:20171101123650j:plain

発表時間は4分。タイトルも「武士道TOURS!!名古屋の巻」うまくいくかドキドキでしたが、審査員の方にも巻物を触っていただき、質疑応答時に「いいアイデア」といってもらえたのが印象的でした。

f:id:ueponx:20171101130039j:plain

結果は、残念ながら受賞には至らなかったものの、チームの満足度は非常に高くとても楽しいハッカソンでした。

今回のハッカソンでは良い結果ではありませんでしたが、いままであったことのないジャンルの方と話ができましたしいい経験になりました。実際の仕事ではこんな事は殆どないので本当にありがたいことです。

f:id:ueponx:20171101124022j:plain

最優秀・優秀チームは引き続きプロダクトをブラッシュアップし、実証実験まで行うようです。ハッカソンで終わりではなく、これからがスタートとなります。がんばってください!

f:id:ueponx:20171101131358j:plain

チームのみなさまもお疲れ様でした。また、お会い出来るのを楽しみにしております。

f:id:ueponx:20171101135526j:plain

Windows10にUnityインストールしてみる【2017.10.20現在】

Windows10にUnityインストールしてみる【2017.10.20現在】

名古屋でUnity初心者向けのハンズオンを行うことになったので、念のため自分も現在の段階でUnityをインストールしてみます。2017.10.20現在でのインストール情報となりますので、今後画面などは変わっていくと思いますが、ご了承ください。

ハンズオンイベントはこちらです。MashupAwardの一貫としてのハンズオンとなります。(MAの名古屋予選はもう終わっていたりしますが)大阪、福井、名古屋で開催し、今後は大垣でも開催が決定しています。

mashup-nagoya.connpass.com

 インストール作業

では、インストールを行いましょう。

ダウンロード

まずは公式サイトでインストーラーダウンロードします。

unity3d.com

画面内にある【プラン選択&ダウンロード】ボタンをクリックします。

f:id:ueponx:20171020171517j:plain

画面が遷移したら左側のPersonalの欄の【Persoinalを試す】をクリックします。

f:id:ueponx:20171020171529j:plain

更に画面が遷移して…

f:id:ueponx:20171020171545j:plain

画面を下にスクロールさせて、【ダウンロードするバージョンを選択してください】の下にある【Windows】ボタンをクリックします。

f:id:ueponx:20171020171554j:plain

少しするとインストーラのファイルのダウンロードが開始されますのでしばらく待ちます。

f:id:ueponx:20171020171605j:plain

指定した、フォルダにUnityDownloadAssistant-2017.2.0f3.exeが作成されていれば成功です。

f:id:ueponx:20171020171615j:plain

インストール作業

インストーラの実行ファイルが入手できたのでインストールを開始します。インストーラをダブルクリックするとインストーラのダイアログが開きます。【Next>】ボタンをクリックします。

f:id:ueponx:20171020171621j:plain

次はライセンスのダイアログ画面に遷移します。ダイアログ下にある【I accept the terms of the License Agreement】のチェックボックスにチェックを入れて、【Next>】ボタンをクリックします。(ライセンス文書は読んだ読んだほうがいいと思います。)

f:id:ueponx:20171020171629j:plain

次はインストールするコンポーネントの選択のダイアログが表示されます。 デフォルトのチェックリストで基本は大丈夫ですが、ちょっと注意なのは【Microsoft Visual Studio Community 2017】です。基本的にはインストールされるのですが、ここでインストールされるコンポーネントUnity開発用のコンポーネントのみなので、通常のデスクトップ開発を行う場合には、デスクトップ開発環境なども別途入れる必要があります。(VisualStudioのインストーラを起動して変更を行えば追加出来ます。)詳しくはページ下部の追記を参照。

f:id:ueponx:20171020171639j:plain

選択が終わったら、【Next>】ボタンをクリックします。続いて表示されるのはインストール先のフォルダ指定のダイアログになります。特に問題が内容であれば、【Next>】ボタンをクリックします。

f:id:ueponx:20171020171647j:plain

次は、Visual Studio 2017のライセンスのダイアログ画面です。ダイアログ下にある【I accept the terms of the License Agreement】のチェックボックスにチェックを入れて、【Next>】ボタンをクリックします。 これでインストールが開始されます。

f:id:ueponx:20171020171657j:plain

かなり時間がかかるので、他の作業を行ったほうがいいと思います。

f:id:ueponx:20171020171706j:plain

インストール作業も後半にくるとVisualStudioのインストールダイアログが表示されます。全く操作はいらないので待機します。 これが終わるとほぼインストール作業もほぼ終わりです。

f:id:ueponx:20171020171737j:plain

VisualStudioのインストールが終わってすぐ、Unityのインストール完了ダイアログが表示されます。ダイアログに【Launch Unity】のチェックボックスがあるのでチェックを入れて【Finish】ボタンをクリックします。これでインストーラが終了し、Unityが起動します。

初回起動時の作業

f:id:ueponx:20171020171726j:plain

Unityのスプラッシュスクリーンが表示されます。自分が以前インストールした時にはこんなにおしゃれだった記憶がありません。

f:id:ueponx:20171020171749j:plain

初回の起動ではUnityのアカウントのサインアップ画面が表示されます。以前はメールアドレスからの登録しかできなかったと思いますが、今ではGoogleアカウント、Facebookアカウントでもサインアップできるようです。すでに登録済みの方は、ログインしてください。新たに登録する方はメール受信することもありますので受信に気をつけてください。(少しかかるようです。)

f:id:ueponx:20171020171759j:plain

ログインができるとライセンスの画面になります。どちらかというと、ProやPlusのバージョンを使用するか、Personalバージョンを使うかの選択になります。ここでは【Personal】にチェックをいれて【Next】ボタンをクリックします。

f:id:ueponx:20171020171807j:plain

次の画面でも【I don't use Unity in a Professional capacity】を選択しておきます。会社や組織などの収入によって使用できるバージョンがあるためです。【Next】ボタンをクリックします。

f:id:ueponx:20171020171826j:plain

これでインストールと初回設定が完了しました。お疲れ様です。【Start Using Unity】ボタンをクリックして次に向かいましょう。

f:id:ueponx:20171020171836j:plain

プロジェクトを作成してみる

2回目以降にUnityを起動するとこのようなダイアログ画面になります。中央の【New Project】ボタンをクリックすると

f:id:ueponx:20171020171844j:plain

プロジェクト設定のダイアログが表示されます。作成するパスや3Dと2Dの選択などを入力して【Create project】ボタンをクリックすると、プロジェクトの生成が行われます。

f:id:ueponx:20171020171852j:plain

そして、以下のような画面が表示されます。あとはハンズオンのお楽しみというところかと思います。

f:id:ueponx:20171020171904j:plain

おわりに

ハンズオン準備のためのインストールということでエントリーを書いてみました。これからがスタートです!楽しいUnityライフをお迎えください!

追記

VisualStudioの設定は【設定】→【アプリと設定】を選択すると参照出来ます。

f:id:ueponx:20171020204132j:plain

検索ボックスでVisual Studioを入力

f:id:ueponx:20171020204146j:plain

Microsoft Visual Studio 2017】の【変更】ボタンをクリック

f:id:ueponx:20171020204645j:plain

インストール済みのVisual Studio Community 2017の【変更】ボタンをクリック

f:id:ueponx:20171020204656j:plain

ワークロードタブを下にスクロールすると

f:id:ueponx:20171020203946j:plain

【Unityによるゲーム開発】”のみ”にチェックがついていることがわかるかと思います。

UnityからVisualStudioのインストールを選択すると、【Unityによるゲーム開発】のモジュールがインストールされますが、デスクトップアプリなどの開発ができる【.NET デスクトップ開発】や【ユニバーサルWindowsプラットフォーム開発】はインストールされません。もし追加したければ、ここでチェックをつけることで追加インストールも出来ます。

「IoT×API de 街ハック!#MA_2017 名古屋ハッカソン予選」に参加してきました

「IoT×API de 街ハック!#MA_2017 名古屋ハッカソン予選」に参加してきました

f:id:ueponx:20171020001426p:plain

mashupawards.connpass.com

10月14日・15日に名古屋工業大学さんで行われたMashupAward名古屋予選に参加してきました。 今回は、一般参加でもあり、運営のお手伝いもさせていただきました。

f:id:ueponx:20171019144024j:plain

f:id:ueponx:20171019144038j:plain

会場に到着して会場準備作業へ、一番の難関はPepper2台の運搬。天気は微妙でしたがなんとか雨は保ってくれました。

f:id:ueponx:20171019233814j:plain

当日は欠席者もほとんど出ず、逆にお手伝いに駆けつけてくれる方も来てくれてかなり助かりました。

今年のMA_2017の初期のカレンダーをみると、実は名古屋の開催はスケジュールに含まれていなかったのですが、 名古屋で開催してほしいと要望を出したところ、うまくことが運び、開催に至ることができました。 ただ、この日は色々な行事との重なりなどがあり、事前ではあまり参加者の伸びが芳しくなかったです。 ただ、告知やLTなどにも行くようにしたこともあり、初参加の方とベテランの方のバランスがいい感じになったような気がします。(直前のIoTLT、GeekBar、Code for Nagoyaが効いたかなと思います)

f:id:ueponx:20171019144504j:plain

今回のイベントは鈴木まなみさんがファシリテーションを行ってもらっていたのですが、自分はまなみさんの ファシリテーションは初めてだったのでかなり新鮮でした。

f:id:ueponx:20171019144636j:plain

ハッカソンのテーマは「IoT×APIで街ハック」の3つのキーワードを絡めてでした。「街」というと町おこしというイメージがありますが、生活するフィールドとして捉えて、それを楽しく!尖った感じ!にアイデアを考えようと捉えていました。

f:id:ueponx:20171019144610j:plain

自分としては街にある既存のものを面白くするのもどうかなと思っていたのですが、それだとアイデアとしては「ありきたり」なのでもっとぶっ飛んだ何かを作らないとだめかなと思いました(MAは一応コンテストなので評価されるものなので)

念のため審査基準

  • チャレンジ度(ぶっ飛び度、変化球、新規性、アイデア
  • ギーク度(突き抜け度、こだわり度、完成度)
  • ワクワク感(表現手法、体験、人を楽しませる仕組み、デザイン)

後は、ハッカソンのテーマ性がこれに加わる感じです。(今回であれば「街」というキーワードとなります。)

一日目の午前中は、参加者みんなでアイデアソンと企業の皆さんからのインプットと続き、その後チームビルディングへと進みます。冒頭で自己紹介があったのは初めて体験したような気がします。

f:id:ueponx:20171019233400j:plain

私は一日目のこの時間が一番楽しい時間だと思っているので、まだハッカソンを経験したことのない方は是非体験してほしいと思っています。実際にものづくりになると、個人のスキルなどに依存する作業が多くなります。しかし、この時点でのアイデア出しはそういうこととは関係なくテーマに対して自由な発想で考えて行くことができます。

今回ご提供頂いたテクニカルサポート企業(APIなど)は以下のような感じでした。

f:id:ueponx:20171019234521j:plain f:id:ueponx:20171019234554j:plainf:id:ueponx:20171019234602j:plainf:id:ueponx:20171019234609j:plainf:id:ueponx:20171019234620j:plain

他にも持ち込み機材として

がありました。

自分が今回出したアイデアは過去の既視感を音楽や環境音で表現するような感じで、訪れた場所や人に身に着けたセンサーなどでその音楽を味付けする感じのもの(過去あった建造物ものに関連する環境音とか)だったような気がします。(あんまり記憶がない…)タイトルは「デジャーブ」

f:id:ueponx:20171019160611j:plain

その後、マホーのキーワード

f:id:ueponx:20171019145241j:plain

これを唱えながら、チーム結成を行っていきます。

今回は比較的似ていたアイデアを融合させて以下のような、「JamPepper」を作ることにしました。 Pepper、センサーなどを組み合わせるところが技術的なポイントです。これを街のホットスポットに設置してジャム・セッションを行って、街を楽しくしていこうというものになります。

【JamPepper草稿】 f:id:ueponx:20171019145322j:plain

このアイデアではPepperとセンサーを通信でつなぐのですが、自分はセンサーデータをサーバ側にアップロードする担当になりました。持ち込みのセンサーに3次元ジャイロ(Grove接続)があったのでそれと、個人で持ち込んでいたNefryBT(きびだんごで購入)を使い、Wifi経由でサーバ(今回はローカルサーバ)へセンサー情報を送っています。

ジャイロセンサー(温度センサーも入っている…すげ)

www.seeedstudio.com

NefryBT(ESP32でWiFiもBLEもいけて、Groveコネクタもある)

kibidango.com

ジャイロのデータはすぐ取得できた(さすがGrove接続!)ので通信部分を頑張っていたのですが、グローバル通信ではうまくいくのにローカルでは送れないという状況になり、そこで半日ほど使ってしましました。全体的な開発状況としては30%も行ってなかったような感じでかなり課題の残る一日目でした。

一日目の夜にNefryBTの作者のわみさんに通信動作に関してDメッセージで質問したりしたのですが、アドバイス頂いた処理を使っても、結局動作できず一日目の深夜が終わりました。深夜にご対応していただいてありがとうございます>わみさん

2日目の早朝にもう一度通信テストを行ってみると、問題なく動作していました。うまく行かなかったソースがなにもしなくて動作していたので小人の仕業かと思ってしました。でも少しソースをいじって(IPアドレス程度)NefryBTに書き込みをすると通信ができなくなる様でした。

個人的な予想なのですが、開発している際にリセットなどを頻繁に行っているためにIPアドレスの取得がうまく行かなくなることがあるのかなと考えました。(起動ログではIPは取れていると出ていますがpingすると疎通できていない感じ)この現象は簡単には解決できそうになかったので、まずはセンサー情報をシリアル経由でサーバ側にアップすることにし、時間があれば通信を行うという方向にしました。(デモでは無線通信はつかえませんけど)

かたや、Pepper側もなかなか難しい状況で開発環境のCoregraphの調子やPepperとの接続が悪くなったりということが突然やってきたりして大変だったようです。

そんなこんなで2日目の午前はあっという間に過ぎ、2日目の昼食が終わると残り2時間という感じになります。デモ中心の発表になるのでそこからはどれぐらいエッセンスを見せられるかを絞っての開発・調整となりました。

15:30ハッキングタイム終了です。

今回のハッカソンでは合計5チーム(※)が結成されて、発表をしています。(※1チームはボッチソンでしたが)

審査員は名古屋大学の河口先生、北名古屋市議の桂川さん、IAMAS小林先生だったので、かなり仕上がりとプレゼンの出来をバキうちされるのではないかと、ヒヤヒヤしていたのですがなんとかなったようです。

開発ばかりで頭が辛かったので、今回のプレゼンではペッパーとダンスをするパフォーマンスをしてみました。

f:id:ueponx:20171019145018j:plain f:id:ueponx:20171019145029j:plain

結果!ハッカソン最優秀賞は「CoT-Claimer of Toilet-」チーム名(QoT)となりました。汚いトイレの公開処刑はいいワードです。

f:id:ueponx:20171019144859j:plain f:id:ueponx:20171019235649j:plain f:id:ueponx:20171019144828j:plain

自分のチームはKonashi賞をいただけました(ありがたい)

hacklog.jp

センサーをハッカソンで使うのはかなり予習をしていないとだめだなーというのが今回の反省です。でも、久しぶりに頑張ってコードを書いていたので満足感半端なかったです。通信部分も含めてもう少しブラッシュアップしたいなと思っています。(予選通過したものよりその後ブラッシュアップしたもののほうが2次予選でいい成績を残すものも多いらしいので。)

ただPepperはないからなあ…と思っていたら、期間中は名古屋工業大学さんで使えるようになるそうです。

今回、名古屋でMAのハッカソンがないのはヤダーというところからのスタートでしたが、無事に開催し終了を迎えることができて本当に良かったです。こういうイベントは一度なくなるとなかなか復帰するのが大変そうだったので、あえて無理をしてでも開催したいと思っていました。

今回、無理を言って会場をお貸し出しいただいた白松先生本当にありがとうございました。 また、テクノロジーサポート企業の方々、まなみん、伴野さん、そして参加されたみなさんも本当にありがとうございます。

来年も名古屋でハッカソンのイベントやりたいです!

ちなみにこの一件をきっかけにIT系のコミュニティを立ち上げました。Mashup名古屋というコミュニティになります。正式にはまた告知をしようと思っています。

RaspberryPiでRFID-RC522を使ってみる【失敗編】

RaspberryPiでRFID-RC522を使ってみる【失敗編】

このエントリーは失敗編です。失敗に至るメモのため、情報が基本ないので読み飛ばしてください。

以前の勉強会で教えてもらった(もう数年も前になりますが)NFCのタグシールを何かに使えないかと思って購入してみました。そのまま使うのもなんなのでArduinoやRaspberryPiでも使えないかなと思って以下も同時に購入してみました。

リーダーもこの値段で購入できるんですね。いい時代なのか、それともちょっとやそっとではお金を稼ぐことができない時代なのか。

このリーダーをネットで検索すると、こちらのリンクにヒットしました。結構Arduinoのネタは多いようなんですが、RaspberryPiはすくないようです。

webcache.googleusercontent.com

ふむふむと読んでいくと…

・the kernel to use Device Tree?
 で Noを選択します。(コレ重要!)

raspi-configコマンドで表示されるメニューで設定値が表示されるようなのですが、うちのRaspberryPiでは表示されないようです。なぜ?カーネルのバージョンなどで違いがあるのでしょうか。念のため、昔使っていたRaspberryPi2でも同様の設定は出ませんでしたし。ネットを検索してもそれっぽい情報はありませんでした。

とりあえず、とても嫌な予感がしますが、そのまま進めていくことにします。

候補としては以下の2つになると思います。そろそろC言語はつらいので…

  • SPI-Py(SPI制御ライブラリ)&MFRC522-pythonの組合せ
  • pi-rc522

今回は、候補の中で使用するのはPythonからこのリーダーを扱えるpi-rc522モジュールになります。 リンク先のページではgitでCloneしてインストールしていますが、ヌルいPython使いの自分はpipでインストールしました。

github.com

$ pip install pi-rc522
Collecting pi-rc522
  Downloading pi-rc522-2.2.1.tar.gz
Collecting RPi.GPIO (from pi-rc522)
  Downloading RPi.GPIO-0.6.3.tar.gz
Collecting spidev (from pi-rc522)
  Downloading spidev-3.2.tar.gz
Building wheels for collected packages: pi-rc522, RPi.GPIO, spidev
  Running setup.py bdist_wheel for pi-rc522 ... done
  Stored in directory: /home/pi/.cache/pip/wheels/83/45/21/0bc28b47c8dfb87d00d806b10c8ffb733e36a8b927668ce42b
  Running setup.py bdist_wheel for RPi.GPIO ... done
  Stored in directory: /home/pi/.cache/pip/wheels/ae/4d/3b/e924997dbf06810adf3b2e37f1d9627b2327eb9cbb285949c9
  Running setup.py bdist_wheel for spidev ... done
  Stored in directory: /home/pi/.cache/pip/wheels/e4/9b/5f/cf0ec030fc958b72315a15412130e4e1dc6040cdb490aa21fb
Successfully built pi-rc522 RPi.GPIO spidev
Installing collected packages: RPi.GPIO, spidev, pi-rc522
Successfully installed RPi.GPIO-0.6.3 pi-rc522-2.2.1 spidev-3.2

同時にGPIOやSPIのモジュールもインストールされるようです。GitでCloneするとサンプルコードも同時に手に入るのですが、pipインストールでは手に入らないので、Githubにいってサンプルを取得します。

【サンプルページ】 github.com

$ wget https://raw.githubusercontent.com/ondryaso/pi-rc522/master/examples/Read.py
--2017-09-18 03:08:03--  https://raw.githubusercontent.com/ondryaso/pi-rc522/master/examples/Read.py
raw.githubusercontent.com (raw.githubusercontent.com) をDNSに問いあわせています... 151.101.72.133
raw.githubusercontent.com (raw.githubusercontent.com)|151.101.72.133|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 983 [text/plain]
`Read.py' に保存中

Read.py             100%[===================>]     983  --.-KB/s    in 0s

2017-09-18 03:08:03 (6.98 MB/s) - `Read.py' へ保存完了 [983/983]

RFIDのリーダーとの接続は RC522側の IRQだけ接続不要です。

RC522モジュール RaspberryPi
1 3.3V GPIO +3.3V(3V3)
2 RST GPIO GPIO25
3 GND GPIO GND(GND)
4 MISO GPIO MISO(GPIO9)
5 MOSI GPIO MOSI(GPIO10)
6 SCK GPIO SCLK(GPIO11)
7 SDA GPIO CE0(GPIO8)

以下のように実行すればうまく…

【Read.py】

#!/usr/bin/env python

import signal
import time
import sys

from pirc522 import RFID

run = True
rdr = RFID()
util = rdr.util()
util.debug = True

def end_read(signal,frame):
    global run
    print("\nCtrl+C captured, ending read.")
    run = False
    rdr.cleanup()
    sys.exit()

signal.signal(signal.SIGINT, end_read)

print("Starting")
while run:
    rdr.wait_for_tag()

    (error, data) = rdr.request()
    if not error:
        print("\nDetected: " + format(data, "02x"))

    (error, uid) = rdr.anticoll()
    if not error:
        print("Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3]))

        print("Setting tag")
        util.set_tag(uid)
        print("\nAuthorizing")
        #util.auth(rdr.auth_a, [0x12, 0x34, 0x56, 0x78, 0x96, 0x92])
        util.auth(rdr.auth_b, [0x74, 0x00, 0x52, 0x35, 0x00, 0xFF])
        print("\nReading")
        util.read_out(4)
        print("\nDeauthorizing")
        util.deauth()

        time.sleep(1)

はずだ…

$ python Read.py
Starting

10分後…全く動かねえ…

ではということで

方法その1であった、SPI-Py(SPI制御ライブラリ)&MFRC522-pythonの組合せもやってみます。

$ git clone https://github.com/lthiery/SPI-Py.git
$ cd SPI-Py
$ sudo python setup.py install
$ cd ..
$ git clone https://github.com/mxgxw/MFRC522-python.git
$ cd MFRC522-python
$ sudo python Read.py

これでも動作せず。/(^o^)\オワタ。

もう少し調べてみる。

ハード側が怪しいということも疑って、Aruduinoでも使用可能なのでそちらでハード側のテストを行ってみました。 Arduinoでやっている例は結構あるので、こちらのほうが楽かなとは思いますが、Unoでは電圧が5V系なのでその部分は注意が必要です。(リーダー系は3.3V系なので)

Arduinoで近距離無線通信 RFID-RC522 NFC by ボクにもわかる地上デジタル

github.com

f:id:ueponx:20170918044058p:plain

実際に動作させてみると…一応、リードできてる?UIDは普通に読めていますがデータブロックは読み取れていません。 (たまにブロックは読み込めることもある…。RFIF側のUIDの読み取りに空振ることもあるぽい…。) ハード的にはかなり怪しいようです。

粘ってみる…その1

更に情報をネットを検索すると

Raspberry PI 3 and RFID-RC522 Problem reading data - Raspberry Pi Forums

なる情報もdtoverlay=spi0-hw-cs/boot/config.txtの設定の追加のようです。

$ sudo vim /boot/config.txt

【変更前】

(略)
# Uncomment some or all of these to enable the optional hardware interfaces
dtparam=i2c_arm=on
#dtparam=i2s=on
dtparam=spi=on
(略)

↓ 【変更後】

(略)
# Uncomment some or all of these to enable the optional hardware interfaces
dtparam=i2c_arm=on
#dtparam=i2s=on
dtparam=spi=on
dtoverlay=spi0-hw-cs
(略)

dtはDeviceTreeの略のようです、最近ではraspi-configではなく/boot/config.txtで設定を行う様です。 でも、こちらを追加したのですが駄目でした。

粘ってみる…その2

ならばということでそもそもOSを変えてやれってバージョンを2つ落として2015-05-05-raspbian-wheezyにしてみました。 これで動かなかったらハードだろぐらいの気持ちです。

wheezyでは、jessie以降にはなかったDevice Treeの設定はちゃんとraspi-configコマンド内にも有効無効は存在しています。 それを設定すると検索でヒットするものと同じ状態になるみたいです。

$ dmesg  | grep spi
[    6.733677] bcm2708_spi bcm2708_spi.0: master is unqueued, this is deprecated
[    7.008711] bcm2708_spi bcm2708_spi.0: SPI Controller at 0x20204000 (irq 80)

$ lsmod |grep spi
regmap_spi              2307  1 snd_soc_wm8804
spi_bcm2708             6018  0

$ ls /dev/spidev* -l
crw-rw---T 1 root spi 153, 0  11  1970 /dev/spidev0.0
crw-rw---T 1 root spi 153, 1  11  1970 /dev/spidev0.1

ですが、動作しません。ムキー。

f:id:ueponx:20170918155520p:plain

粘ってみる…その3

よくわからない気分になってきたので、更に粘ってみました。今度はIchigoJamです。

fukuno.jig.jp

ドライバーもなにもないので、これでだめならハードが悪い(もうそんな気分ですが)と諦められます。

f:id:ueponx:20170918165753j:plain

結果、駄目でした…読み取り待ちにはなってくれるのですが、それ以上の処理には続かないようです。 このためにIchigoJamの使い方をさらに勉強とは、すごい自分にもやる気があるんだなと思いました(棒)

f:id:ueponx:20170918155910p:plain

終わりに

ハードさえ動けばやりたいこと全部やりきった感あります。 新規にハード買うかして再チャレンジしたいと思います。

f:id:ueponx:20170918160821p:plain

2日使ったのでかなり寝たいです。

RaspberryPiでTwitterのタイムラインを読み上げてみる(Amazon Polly & Twitter & Python)

RaspberryPiでTwitterのタイムラインを読み上げてみる(Amazon Polly & Twitter & Python

以前のエントリーでAmazon Polly(以下Polly)を使っていましたが、流石にもう少しちゃんと動くものを作ってみようかなと思います。具体的にはTwitterのタイムラインを取得してそれを読み上げようと思います。これまでも似たようなものとして、OpenJTalkで読み上げを行っていましたがOpenJTalkでは文章量が長くなると途中できれてしまうということが稀にあり、Pollyではそんなこともないと信じたいのでチャレンジしてみました。(Pollyは有料サービスなんでそんなには使えないですけどね)

f:id:ueponx:20170914195730p:plain f:id:ueponx:20170914195636p:plain

この組み合わせは Polly & Twitterバードの鳥鳥コンビなのはちょっと楽しい。

インストール

TwitterのタイムラインをPythonで取得するtweepyは以前のエントリーでも使っていますが、かなり前の話なので念のためインストールについても書いておきます。といってもpipを使えばそれでOKです。

uepon.hatenadiary.com

$ sudo pip install tweepy
Collecting tweepy
  Downloading tweepy-3.5.0-py2.py3-none-any.whl
Requirement already satisfied: six>=1.7.3 in /usr/lib/python2.7/dist-packages (from tweepy)
Requirement already satisfied: requests>=2.4.3 in /usr/local/lib/python2.7/dist-packages (from tweepy)
Requirement already satisfied: requests-oauthlib>=0.4.1 in /usr/lib/python2.7/dist-packages (from tweepy)
Requirement already satisfied: oauthlib>=0.6.2 in /usr/lib/python2.7/dist-packages (from requests-oauthlib>=0.4.1->tweepy)
Installing collected packages: tweepy
Successfully installed tweepy-3.5.0

とても簡単です。

あとはPollyですが、これでも以前のエントリーを参考にしてインストールしておきます。bot3のインストールを行えばOKです。

uepon.hatenadiary.com

これでPythonからTwitterPollyを使う準備が整いました。

読み上げプログラムを作ってみる

行おうとしているプログラムは基本的には以下の動作から構成されます。

  • Twitterの認証(tweepyモジュールの使用)
  • タイムラインの取得(tweepyモジュールの使用)
  • タイムラインの不要な部分の削除(正規表現:reモジュールの使用)
  • Pollyへテキストの送信とファイルへの保存(bot3へのアクセス)
  • pygameのmixerで再生

こちらがソースの全体となります。(関数化とかしてない…)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import tweepy
import re
import datetime

from boto3 import Session
from botocore.exceptions import BotoCoreError, ClientError
from contextlib import closing
import os
import sys
import subprocess
import pygame.mixer
import time

# 個別にTwitterクライアント作成時に設定されるCONSUMER_KEY、CONSUMER_SECRETを設定してください
CONSUMER_KEY = 'XXXXXXXXXXXXXXXXXXX'
CONSUMER_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth_url = auth.get_authorization_url()

print('Please authorize: ' + auth_url)
verifier = raw_input('PIN: ').strip()

auth.get_access_token(verifier)

print("ACCESS_KEY = '%s'" % auth.access_token)
print("ACCESS_SECRET = '%s'" % auth.access_token_secret)

ACCESS_KEY = auth.access_token
ACCESS_SECRET = auth.access_token_secret

auth.set_access_token(ACCESS_KEY, ACCESS_SECRET)
api = tweepy.API(auth)
print(api.me().name)

now = datetime.datetime.now()
print(now)

# api.update_status('Tweepy! Sample start! ' + str(now))

session = Session(region_name="us-west-2")
polly = session.client("polly")

public_tweets = api.home_timeline()
for i, tweet in enumerate(public_tweets):
    print('---{}---'.format(i))
    print(tweet.author.screen_name + ":")
    # print(tweet.text)

    text = re.sub('RT', "", tweet.text)
    text = re.sub(r'https?://[\w/:%#\$&\?\(\)~\.=\+\-…]+', "", text)
    text = re.sub(r'[##]([\w一-龠ぁ-んァ-ヴーa-z]+)', "", text)
    text = re.sub(r'@([\w]+):', "", text)
    text = re.sub('\s', "", text)

    print(text)

    try:
        response = polly.synthesize_speech(
            Text=text, OutputFormat="mp3", VoiceId="Mizuki")
    except (BotoCoreError, ClientError) as error:
        print(error)
        sys.exit(-1)
    if "AudioStream" in response:
        with closing(response["AudioStream"]) as stream:
            output = "speech.mp3"
            try:
                with open(output, "wb") as file:
                    file.write(stream.read())
            except IOError as error:
                print(error)
                sys.exit(-1)
        print("synthesize_speech OK ->>" + output)
    else:
        print("Could not stream audio")
        sys.exit(-1)

    pygame.init()
    pygame.mixer.init()
    pygame.mixer.music.load("speech.mp3")
    pygame.mixer.music.play()
    print("PLAY")
    while pygame.mixer.music.get_busy() == True:
        continue
    print("END")

    pygame.mixer.music.stop()
    pygame.mixer.quit()
    pygame.quit()

ソースの説明

以下では部分的に説明をしていきます。

Twitterの認証(tweepyモジュールの使用)

以下の部分でTwitterに関する認証を行っています。 CONSUMER_KEYCONSUMER_SECRETTwitterのアプリの作成画面に出ます。これを使って認証用のURLを呼び出し、PIN生成を行っていきます。 表示されるURLをブラウザに与えることでPIN表示まで持っていきます。

f:id:ueponx:20170916083004p:plain

起動すると以下のようなPINの入力待ち画面になります。

f:id:ueponx:20170914222010p:plain

この処理を行っているのが以下の処理になります。

CONSUMER_KEYCONSUMER_SECRETの値がXXXXX…となっていますがTwitterのアプリケーション設定画面の

  • Consumer Key (API Key)
  • Consumer Secret (API Secret)

の値を入れるようにしてください。

f:id:ueponx:20170914222407p:plain

Pythonの処理部分】

# 個別にTwitterクライアント作成時に設定されるCONSUMER_KEY、CONSUMER_SECRETを設定してください
CONSUMER_KEY = 'XXXXXXXXXXXXXXXXXXX'
CONSUMER_SECRET = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth_url = auth.get_authorization_url()

print('Please authorize: ' + auth_url)
verifier = raw_input('PIN: ').strip()

表示されたURLをクリックすると

f:id:ueponx:20170914222645p:plain

認証画面に遷移します。【連携アプリを認証】をクリックします。(ログインを事前にしていないと、ログインを促された後にこの画面になるかもしれません。)

f:id:ueponx:20170914222912p:plain

すると7桁のPINコードが表示されるので、この値をコンソールに入力します。

PINを入力すると実際に使用するACCESS_TOKENACCESS_TOKEN_SECRETを取得する処理となります。

Pythonの処理部分】

auth.get_access_token(verifier)

print("ACCESS_KEY = '%s'" % auth.access_token)
print("ACCESS_SECRET = '%s'" % auth.access_token_secret)

ACCESS_KEY = auth.access_token
ACCESS_SECRET = auth.access_token_secret

auth.set_access_token(ACCESS_KEY, ACCESS_SECRET)
api = tweepy.API(auth)

これでアプリケーションの使用に必要なACCESS_KEYACCESS_TOKEN_SECRETの取得ができました。あとは認証処理に与えれば完了となりますauth.set_access_token(ACCESS_KEY, ACCESS_SECRET)の部分になります。これでTwitter APIの処理を行える様になりました。 本来であればこれらキーはファイルに保存して再利用するのですが、今回は端折っています。保存する場合にはアクセス権などには注意してください。

タイムラインの取得(tweepyモジュールの使用)

APIの使用ができるようになればタイムラインの取得は簡単です。今回はHomeタイムラインを取得しています。

Pythonの処理部分】

public_tweets = api.home_timeline()
for i, tweet in enumerate(public_tweets):
    print('---{}---'.format(i))
    print(tweet.author.screen_name + ":")
    # 表示する場合には以下のコメントを外してください
    # print(tweet.text)

取得したタイムラインはデフォルト件数は20件になります。必要であれば引数に追加を与えることになりますが、Pollyが有料サービスなのでこのままにしておきます。

タイムラインの不要な部分の削除(正規表現:reモジュールの使用)

タイムラインの文面から不要なURLなどを正規表現で削除して読み上げに適した文面に変換します。さすがにURLを読み上げられても?となってしまうので。

以下は正規表現でURL、【RT】接頭辞、ハッシュタグ、ユーザ名の削除を行いプレーンな文章に変換をして行きます。

Pythonの処理部分】

    text = re.sub('RT', "", tweet.text)
    text = re.sub(r'https?://[\w/:%#\$&\?\(\)~\.=\+\-…]+', "", text)
    text = re.sub(r'[##]([\w一-龠ぁ-んァ-ヴーa-z]+)', "", text)
    text = re.sub(r'@([\w]+):', "", text)
    text = re.sub('\s', "", text)

これで完璧というわけではないのですがおおよそ大丈夫かなと思います。

Pollyへテキストの送信とファイルへの保存(bot3へのアクセス)

得られたタイムラインのデータをbot3にアクセスして、Pollyが読み上げした音声のデータを取得していきます。

このあたりは過去エントリー参照で大丈夫でしょう。

uepon.hatenadiary.com

Pythonの処理部分】

    print(text)

    try:
        response = polly.synthesize_speech(
            Text=text, OutputFormat="mp3", VoiceId="Mizuki")
    except (BotoCoreError, ClientError) as error:
        print(error)
        sys.exit(-1)
    if "AudioStream" in response:
        with closing(response["AudioStream"]) as stream:
            output = "speech.mp3"
            try:
                with open(output, "wb") as file:
                    file.write(stream.read())
            except IOError as error:
                print(error)
                sys.exit(-1)
        print("synthesize_speech OK ->>" + output)

この処理が終わるとPollyで生成された音声ファイルはspeech.mp3とされて保存されます。

pygameのmixerで再生

あとは変換された音声を再生するだけです。

Pythonの処理部分】

    pygame.init()
    pygame.mixer.init()
    pygame.mixer.music.load("speech.mp3")
    pygame.mixer.music.play()
    print("PLAY")
    while pygame.mixer.music.get_busy() == True:
        continue
    print("END")

    pygame.mixer.music.stop()
    pygame.mixer.quit()
    pygame.quit()

こちらも先程のエントリーを参考にしてもらえればと思います。(初期化処理・終了処理は毎回しなくてもいいかなとは思いますが。)

終わりに

ようやくPythonを使ってTwitterのタイムラインを取得して読み上げることができました。 まあ、読み上げられた文面もなんとか分かるかなという感じですがAAや絵文字なんかがあると謎の文面になってしまいますね。さすがに仕方ないですね。 長い文章での読み上げがうまくいくなら、ネットワークアクセスがある分遅くなってしまいますのでOpenJTalkの方がいいかも。

コンソールTwitterクライアント```rainbowstream```をつかってみた

コンソールTwitterクライアントrainbowstreamをつかってみた

なんとなく、linux環境でもコンソールでTwitterのタイムラインを見てみたいなあと思って、クライアントをさがしていました。(家で使うのはRaspbianだけなんで気まぐれな欲求なんですが)

その中でもなかなかいいなと思ったのがrainbowstreamでした。

テーマで色分けができたりというのがかなり見やすくていいかなと思いますし、気合を入れれば画面もそれなりにわかるというのもすごいと思います。そういう用途はGUI環境でやればいいとは思いますが。

ってことでインストールしてみました。

rainbowstreamのインストール

以下のリンクを参照にすれば簡単にインストールできます。環境はpythonなので本体はpipでのインストールになりますが、いろいろLibraryの依存があるのでそれも一緒にインストールする必要があります。

github.com

ドキュメントにはvirtualenvを使った方がいいということでしたが、今回は端折ってそのままインストールしています。

$ sudo apt-get install python-dev libjpeg-dev libfreetype6 libfreetype6-dev zlib1g-dev
$ sudo pip install rainbowstream

【参考】 Pipenv & Virtual Environments — The Hitchhiker's Guide to Python

インストールは問題なく終わると思います。(本体以外のLibraryもインストール済みのものがほとんどでした。)

rainbowstreamを実行してみる

実行は以下のようにするだけです。

$ rainbowstream

初回の実行ではTwitterアプリケーションのPIN認証が求められるので

f:id:ueponx:20170913232333p:plain

画面に表示されたURLをクリックしてブラウザで認証を行います。リンクをクリックすると以下のような画面になるので

f:id:ueponx:20170910153740p:plain

【連携アプリを認証】ボタンをクリックします。すると7桁数字のPINが表示されるのでそれをコピーなどしてコンソールに入力します。(画面では伏せています)

※2回目以降の起動では初回起動時の認証情報が~/.rainbow_oauthに格納されるでの認証は不要です。

f:id:ueponx:20170910154556p:plain

するとログインが行われて

f:id:ueponx:20170910154656p:plain

コマンドモードになりますが、このままほっておくと自分のタイムラインが表示されます。

f:id:ueponx:20170910155018p:plain

コマンドマニュアルはこちらになります。

Rainbow Stream — RainbowStream 1.3.7 documentation

おわりに

複数のTLを監視しない範囲であればコマンドラインでの実行でもかなりいいかなと思います。数世代前のPCでLinuxを動かす場合にはこちらは軽快かもしれませんねです。(Aspire one 753 Celeron U3400 / 2GBメモリー / USBメモリブート/ RaspberryPixel86)

本当は、この結果が標準出力されて、それを使ってpollyとかから読み上げでも行おうと思っていたのですが、標準出力はしてくれないようです。残念。 次回では真面目にPythonでTweepyを使ってタイムラインを拾って読み上げをさせてみたいと思います。