AWS Cloud9でCapybara+Selenium+Chrome設定時のエラーとその対処法について[ Everyday Rails 6章 ]

はじめに

Rails チュートリアル」にて開発環境としてAWS Cloud9を使っていたことから、「Everyday Rails - RSpecによるRailsテスト入門」を進める際にも継続してAWS Cloud9を利用しています。

railstutorial.jp

leanpub.com

しかし、6章の「JavaScriptを使った操作をテストする」という項目で記載通りにSelenium+Chromeの設定をし、スペックを実行しようとしてもエラーが出てしまい実行することが出来ませんでした。

本記事では、私が直面したエラーメッセージとその対処法を記載したいと思います。

対象

  • 「Everyday Rails - RSpecによるRailsテスト入門」の6章を進めている途中でエラーによって詰まってしまった人
  • 下記、設定は完了している

spec/rails_helper.rbの以下の行のコメントアウトを外している

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

spec/support/capybara.rbに以下を記述

Capybara.javascript_driver = :selenium_chrome

Gemfileに'chromedriver-helper'を追加

エラーメッセージとその対処法

その1

Selenium::WebDriver::Error::UnknownError: unknown error: cannot find Chrome binary

Amazon LinuxChromeが入っていないことが原因だと考えられます。
下記コマンドを実行し、インストールを行ないましょう。

curl https://intoli.com/install-google-chrome.sh | bash

参考
https://www.t4traw.net/blog/2018/03/awsamazon-cloud9環境でheadless-chromeを使う/


その2

Selenium::WebDriver::Error::UnknownError: unknown error: Chrome failed to start: exited abnormally

spec/support/capybara.rbの記述内容を以下のように修正します。

Capybara.javascript_driver = :selenium_chrome_headless

Capybara.javascript_driver = :selenium_chromeでは実際にChromeを開いてテストしますが、AWS Cloud9ではそれが出来ないのだと思われます。
そのため、ヘッドレスモードを使ってテストをするように設定することで解決します。


その3

NameError: uninitialized constant Selenium::WebDriver::Chrome::Options

「::Selenium::WebDriver::Chrome::Options」はselenium-webdriverのバージョン3.4.1にて追加されたため、それ以上のバージョンにしなければなりません。Gemfileのselenium-webdriverのバージョンを3.4.1以上に設定し、bundle installを実行しましょう。

参考
stackoverflow.com

おわりに

今回、AWS Cloud9にてCapybara+Selenium+Chrome設定時に私が直面したエラーとその対処法についてご紹介しました。
同様のエラーに直面した際の参考になればと思います。

NTPサーバから時刻を取得してM5Stackに表示する

はじめに

M5Stackのスケッチ例に「TFT_Clock_Digital」というものがあります。

デジタル時計のように時刻が画面上に表示され1秒ごとに変化しますが、表示される時刻はコンパイルした時刻が基準となります。
(厳密には違うと思いますが大雑把な認識としてだとお思いください。)

そのため、例えば15:47:00にコンパイルした場合、電源を入れる度に15:47:00がまず表示され、そこから1秒ごとに表示される時刻が変化します。

しかしながら、そのままでは時計としての役割を果たせないため、NTPサーバから時刻を取得して現在の時刻を表示できるものを作成しましたのでご紹介します。

完成品

画面に表示されている文字列の見た目はTFT_Clock_Digitalと同様ですが、こちらは電源ボタンを押して再度起動しても隣の時計とほぼ同じ時刻を表示してくれます。

開発環境

準備物

  • M5Stack Gray

M5Stack Gray(9軸IMU搭載)

M5Stack Gray(9軸IMU搭載)

※M5Stackであればどのシリーズ(Basic,FIRE等)でも問題ないと思います。

前提

Arduino IDEによるM5Stackの開発環境の構築が出来ている方を対象としています。

1.下記のスケッチを書き込む

スケッチ例にある「TFT_Clock_Digital」と「SimpleTime」の合わせ技となっております。
以下にそれぞれのスケッチ例がありますので、参考になるかと思います。

  • TFT_Clock_Digital

ファイル→スケッチ例→M5Stack→Advanced→Display→TFT_Clock_Digital

  • SimpleTime

ファイル→スケッチ例→ ESP32→Time→SimpleTime

#include <M5Stack.h>
#include <WiFi.h>
#include "time.h"

const char* ssid       = "";  
const char* password   = "";

const char* ntpServer =  "ntp.jst.mfeed.ad.jp";
const long  gmtOffset_sec = 9 * 3600;
const int   daylightOffset_sec = 0;


static uint8_t conv2d(const char* p); // Forward declaration needed for IDE 1.6.x

uint8_t hh = conv2d(__TIME__), mm = conv2d(__TIME__ + 3), ss = conv2d(__TIME__ + 6); // Get H, M, S from compile time

byte xcolon = 0, xsecs = 0;

void setup(void) {
  
  Serial.begin(115200);
  M5.begin();
  M5.Lcd.fillScreen(TFT_BLACK);
  M5.Lcd.setTextSize(1);
  M5.Lcd.setTextColor(TFT_YELLOW, TFT_BLACK);

  //connect to WiFi
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("CONNECTED");

  //init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
      struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
    return;
  }
  //disconnect WiFi as it's no longer needed
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);

}

void loop() {
  
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Failed to obtain time");
    return;
  }
  hh = timeinfo.tm_hour;
  mm = timeinfo.tm_min;
  ss = timeinfo.tm_sec;
  
  // Update digital time
  int xpos = 0;
  int ypos = 85; // Top left corner ot clock text, about half way down
  int ysecs = ypos + 24;

  // Draw hours and minutes
  if (hh < 10) xpos += M5.Lcd.drawChar('0', xpos, ypos, 8); // Add hours leading zero for 24 hr clock
  xpos += M5.Lcd.drawNumber(hh, xpos, ypos, 8);             // Draw hours
  xcolon = xpos; // Save colon coord for later to flash on/off later
  xpos += 29;
  if (mm < 10) xpos += M5.Lcd.drawChar('0', xpos, ypos, 8); // Add minutes leading zero
  xpos += M5.Lcd.drawNumber(mm, xpos, ypos, 8);             // Draw minutes
  xsecs = xpos; // Sae seconds 'x' position for later display updates
    
  if (ss % 2) { // Flash the colons on/off
    M5.Lcd.setTextColor(0x39C4, TFT_BLACK);        // Set colour to grey to dim colon
    M5.Lcd.drawChar(':', xcolon, ypos - 8, 8);     // Hour:minute colon
    xpos += M5.Lcd.drawChar(':', xsecs, ysecs, 6); // Seconds colon
    M5.Lcd.setTextColor(TFT_YELLOW, TFT_BLACK);    // Set colour back to yellow
  }else{
    M5.Lcd.drawChar(':', xcolon, ypos - 8, 8);     // Hour:minute colon
    xpos += M5.Lcd.drawChar(':', xsecs, ysecs, 6); // Seconds colon
  }
  
  //Draw seconds
  if (ss < 10) xpos += M5.Lcd.drawChar('0', xpos, ysecs, 6); // Add leading zero
  M5.Lcd.drawNumber(ss, xpos, ysecs, 6);                     // Draw seconds
}


// Function to extract numbers from compile time string
static uint8_t conv2d(const char* p) {
  uint8_t v = 0;
  if ('0' <= *p && *p <= '9')
    v = *p - '0';
  return 10 * v + *++p - '0';
}

参考

qiita.com

おわりに

NTPサーバから時刻を取得してM5Stackに表示する方法をご紹介しました。

Wi-Fiに繋がる環境下であればこちらの方が良いと思いますので、ぜひお試しください。

M5Stackとカラーセンサでカラーピッカーとカラーミキサーを作る

はじめに

先日開催されたROHM OPEN HACK CHALLENGE2018の最終審査に関するツイートが私のタイムラインに流れてきました。
open.rohm.com


どの作品も素晴らしいものでしたが、私が特に好きだったものは優秀賞に選ばれた『絵の具カラーピッカー「絵のピック」』でした。


「絵のピック」について簡単に説明すると、カラーセンサで対象の色を読み取り、読み取った色を実際に絵の具を使用して作ってくれるものです。(詳細は下記参照)
open.rohm.com

この作品を見て、私も似たようなものを作りたいと思いましたが、なかなか実現することが難しいため、簡易的に、かつ似たようなことが出来るものをM5Stackとカラーセンサを用いて作りましたのでご紹介します。

完成品

今回作成した機能は2つです。
1つ目の機能は色の読み取りです(カラーピッカー)。こちらはカラーセンサを用いて実現しています。読み取った色をディスプレイに表示しています。



2つ目の機能は読み取った2つの色を混ぜることです(カラーミキサー)。1つ目の機能を用いて色を2回読み取り、それらを混ぜ合わせた色をディスプレイに表示しています。


開発環境

準備物

  • M5Stack Gray

M5Stack Gray(9軸IMU搭載)

M5Stack Gray(9軸IMU搭載)

※M5Stackであればどのシリーズ(Basic,FIRE等)でも問題ないと思います。

  • カラーセンサ

  • ジャンパーワイヤ(オス-メス)

前提

Arduino IDEによるM5Stackの開発環境の構築が出来ている方を対象としています。

1.M5Stackとカラーセンサを繋ぐ

カラーセンサの接続に関して、こちらを参考に繋ぎました。
nn-hokuson.hatenablog.com

私は以下のようにカラーセンサとM5Stackを繋ぎましたが、M5Stackのピンの仕様について理解できていないのでこれが正しいかは保証できません。ご了承ください。

カラーセンサ M5Stack
S0 1
S1 16
S2 17
S3 21
OUT 22
VCC 5V
0E G
GND G

2.キャリブレーション用のスケッチ例

1.で参考にした記事より引用

センサから得られる値はお使いの環境で多少変化すると思うので、キャリブレーションする必要があります。
白色の紙をセンシングした時のRGB値と、黒色の紙をセンシングした時のRGB値を調べて、whiteRGB、blackRGBの値に代入して下さい。


よって、まずは下記のスケッチを書き込み、キャリブレーションします。こちらも先程の記事内のスケッチを参考にしております。

#include <M5Stack.h>

#define S0 1
#define S1 16
#define S2 17
#define S3 21
#define sensorOut 22

void setup() {
  M5.begin();
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(sensorOut, INPUT);
  
  digitalWrite(S0,HIGH);
  digitalWrite(S1,LOW);
  
  Serial.begin(9600);
}

void loop(void) {
   
  if (M5.BtnA.wasPressed()){
    digitalWrite(S2,LOW);
    digitalWrite(S3,LOW);
    int r = pulseIn(sensorOut, LOW);
    //r = map(constrain(r,blackR,whiteR), whiteR, blackR,0,255);
    delay(100); 
  
    digitalWrite(S2,HIGH);
    digitalWrite(S3,HIGH);
    int g = pulseIn(sensorOut, LOW);
    //g = map(constrain(g,blackG,whiteG), whiteG, blackG,0,255);
    delay(100); 
    
    digitalWrite(S2,LOW);
    digitalWrite(S3,HIGH);
    int b = pulseIn(sensorOut, LOW);
    //b = map(constrain(b,blackB,whiteB), whiteB, blackB,0,255);
    delay(100); 

    Serial.println(String(r) + "," + String(g) + "," + String(b) );
  }
  M5.update();
}


対象物にカラーセンサを当ててM5Stackの左のボタンを押すことでシリアルモニタにRGB値が表示されます。

3.カラーピッカーとカラーミキサーのスケッチ例

下記のスケッチを書き込みます。2.で検出したwhiteRGB、blackRGBにそれぞれ変更してから書き込んでください。

#include <M5Stack.h>

#define S0 1
#define S1 16
#define S2 17
#define S3 21
#define sensorOut 22

int whiteR = 151;
int whiteG = 160;
int whiteB = 120;
int blackR = 14;
int blackG = 14;
int blackB = 11;

boolean flag = false;
int beforeR = 0;
int beforeG = 0;
int beforeB = 0;
int r = 0;
int g = 0;
int b = 0;
int alpha = 128;

uint16_t getColor(uint8_t red, uint8_t green, uint8_t blue){
  return ((red>>3)<<11) | ((green>>2)<<5) | (blue>>3);
}

void setup() {
  M5.begin();
  M5.Lcd.setBrightness(200);
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(sensorOut, INPUT);
  
  digitalWrite(S0,HIGH);
  digitalWrite(S1,LOW);
  
  Serial.begin(9600);
}

void loop(void) {
   
  if (M5.BtnA.wasPressed()){
    beforeR = r;
    beforeG = g;
    beforeB = b;
      
    digitalWrite(S2,LOW);
    digitalWrite(S3,LOW);
    r = pulseIn(sensorOut, LOW);
    r = map(constrain(r,blackR,whiteR), whiteR, blackR,0,255);
  
    digitalWrite(S2,HIGH);
    digitalWrite(S3,HIGH);
    g = pulseIn(sensorOut, LOW);
    g = map(constrain(g,blackG,whiteG), whiteG, blackG,0,255);
    
    digitalWrite(S2,LOW);
    digitalWrite(S3,HIGH);
    b = pulseIn(sensorOut, LOW);
    b = map(constrain(b,blackB,whiteB), whiteB, blackB,0,255);

    Serial.println(String(r) + "," + String(g) + "," + String(b) );
    M5.Lcd.fillScreen(getColor(r,g,b));
  }else if(M5.BtnB.wasPressed()){
    M5.Lcd.fillScreen(getColor(r*((double)alpha/255)+beforeR*(1-(double)alpha/255),g*((double)alpha/255)+beforeG*(1-(double)alpha/255),b*((double)alpha/255)+beforeB*(1-(double)alpha/255)));
  }
  
  M5.update();
}


左のボタンを押すことで色の読み取り、2つの色を読み取った後に真ん中のボタンを押すことで2色を混ぜた後の色がディスプレイに表示されます。


スケッチ作成時に参考にしたもの
qiita.com

oshiete.goo.ne.jp

おわりに

M5Stackとカラーセンサでカラーピッカーとカラーミキサーを作る方法をご紹介しました。

現実世界に存在する色を読み取ってディスプレイに表示できるだけでも楽しいので、良ければ試してみてください。

M5Stack Grayを振ってディスプレイ上の画像を切り替える

はじめに

M5Stack Grayには加速度、ジャイロ、磁気を計測可能な9軸センサ、MPU9250が搭載されています。

本記事ではジャイロセンサを用いて、M5Stack Gray本体を振ることでディスプレイ上の画像を切り替える方法をご紹介します。

完成品

開発環境

準備物

  • M5Stack Gray

M5Stack Gray(9軸IMU搭載)

M5Stack Gray(9軸IMU搭載)

※ M5Stack Basicではジャイロセンサを搭載していないため実現できません。

また、M5Stack FIREについてはMPU6050(三軸加速度センサ・三軸ジャイロセンサ)が搭載されているため、同様のことができるとは思います。

しかしながら、私がM5Stack FIREを所持しておらず動作確認が出来ないため、本記事の対象外とさせていただきます。

前提

Arduino IDEによるM5Stackの開発環境の構築が出来ており、M5Stackのスケッチ例にあるJpegDrawとMPU9250BasicAHRSの動作確認が済んでいる方を対象としています。

以下にスケッチ例がありますので確認してください。

  • JpegDraw

ファイル→スケッチ例→M5Stack→Advanced→Display→JpegDraw

  • MPU9250BasicAHRS

ファイル→スケッチ例→M5Stack→Modules→MPU9250→MPU9250BasicAHRS

1. 画像ファイルの準備

microSDカードにpicturesフォルダを作成し、その中に画像ファイルを何枚か入れます。また、画像ファイルのファイル名を連番となるようにします。

(本記事では画像枚数を3枚、ファイル名をp0.jpg、p1.jpg、p2.jpgとしています。)

2. スケッチ例

Arduino IDEから下記のスケッチを書き込みます。

ポイントとしては本体を振った際のジャイロセンサの値を閾値によって判定し、移動方向(左右)に対応したフラグを立てています。

今回は完成品でご紹介した左に振る→右に振る→画像が切り替わるのスケッチとなっていますが、右に振る→左に振る→何らかの処理も可能です。

#include <M5Stack.h>
#include "utility/MPU9250.h"

MPU9250 IMU;

bool leftFlag = false; //左に動いたことを保持するフラグ
bool rightFlag = false; //右に動いたことを保持するフラグ

int maxPicSize = 3; //SDカード内に入れた画像の枚数
int th = 80;
int count = 1;

void setup()
{
  M5.begin();
  Wire.begin();
  M5.Lcd.setBrightness(100);
  M5.Lcd.drawJpgFile(SD, "/pictures/p0.jpg");
  byte c = IMU.readByte(MPU9250_ADDRESS, WHO_AM_I_MPU9250);
  IMU.calibrateMPU9250(IMU.gyroBias, IMU.accelBias);
}

void loop()
{
  if (IMU.readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01){  
    IMU.readGyroData(IMU.gyroCount);  // Read the x/y/z adc values
    IMU.getGres();
    IMU.gz = (float)IMU.gyroCount[2]*IMU.gRes;
  } 
  IMU.delt_t = millis() - IMU.count;
  if (IMU.delt_t > 100){
    int accel = (int)(IMU.gz);
    if(accel < -th){
      if(leftFlag){
        //左に振る→右に振るの後の処理
         M5.Lcd.fillScreen(BLACK);
         int num = count++ % maxPicSize;
         String s = "/pictures/p"+String(num)+".jpg";
         M5.Lcd.drawJpgFile(SD, s.c_str());
      }else{
        rightFlag = true;
      }
    }else if(accel > th){
      if(rightFlag){
        //右に振る→左に振るの後の処理
        
      }else{
        leftFlag = true;
      }
    }else{
      leftFlag = false;
      rightFlag = false;
    }
    IMU.count = millis();
  } 
}

3. M5Stack Grayを振る

振りましょう。

おわりに

M5Stack Grayを振ってディスプレイ上の画像を切り替える方法をご紹介しました。

今回は画像の切り替えでしたが、画像の表示部分を別の処理に書き換えることで、振る→何らかの処理をするということも実現できると思います。

ESP32とAmazon Alexaを連携して物理スイッチを制御する

はじめに

前回の記事でESP32をAmazon Alexa(以下、Alexa)のスマートホームのデバイスに登録する方法をご紹介しました。

kuracux.hatenablog.jp


記事内では動作確認のためにLEDの点灯・消灯を制御していましたが、SwitchBotのような物理スイッチの制御を実現してみましたのでご紹介します。

完成品

AlexaアプリからESP32に接続されたサーボモータを制御しています。また、Amazon Echoに話しかけても動作可能です。

見た目は残念ですが、物理スイッチの制御を実現しています。

また、通常のように物理スイッチを指で押すことも可能となっています。


開発環境

準備物

  • Alexaアプリ
  • ESP32-DevKitC

akizukidenshi.com

  • ブレッドボードとジャンパーワイヤ(オス-オス)

akizukidenshi.com

前提

前回の記事を参考にESP32とAlexaとの連携がすでに済んでいる方を対象としています。

1 スケッチ例

Arduino IDEから下記のスケッチを書き込みます。前回の記事のスケッチをもとに作成しています。

#include <Arduino.h>
#include <WiFi.h>
#include "fauxmoESP.h"
#define SERIAL_BAUDRATE                 115200
#define SERVO                           15

fauxmoESP fauxmo;

char ssid[] = "";
char password[] = "";
bool inputState = true; //オンオフ記録用

// -----------------------------------------------------------------------------
// Wifi
// -----------------------------------------------------------------------------

void wifiSetup() {

    // Set WIFI module to STA mode
    WiFi.mode(WIFI_STA);

    // Connect
    Serial.printf("[WIFI] Connecting to %s ",ssid);
    WiFi.begin(ssid, password);

    // Wait
    while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(100);
    }
    Serial.println();

    // Connected!
    Serial.printf("[WIFI] STATION Mode, SSID: %s, IP address: %s\n", WiFi.SSID().c_str(), WiFi.localIP().toString().c_str());

}

void setup() {

    // Init serial port and clean garbage
    Serial.begin(SERIAL_BAUDRATE);
    Serial.println();
    Serial.println();

    // Wifi
    wifiSetup();

    // You have to call enable(true) once you have a WiFi connection
    // You can enable or disable the library at any moment
    // Disabling it will prevent the devices from being discovered and switched
    fauxmo.enable(true);

    // Add virtual devices
    fauxmo.addDevice("照明");

    // fauxmoESP 2.0.0 has changed the callback signature to add the device_id,
    // this way it's easier to match devices to action without having to compare strings.
    fauxmo.onSetState([](unsigned char device_id, const char * device_name, bool state) {
        Serial.printf("[MAIN] Device #%d (%s) state: %s\n", device_id, device_name, state ? "ON" : "OFF");
        inputState = state;
        if(inputState){
          //オンのときのサーボの挙動を記述
          ledcWrite(0,60);
          delay(500);
          ledcWrite(0,40);
        }else{
          //オフのときのサーボの挙動を記述
          ledcWrite(0,25);
          delay(500);
          ledcWrite(0,40);
        }
    });

    // Callback to retrieve current state (for GetBinaryState queries)
    fauxmo.onGetState([](unsigned char device_id, const char * device_name) {
        return inputState == HIGH;
    });
    
    ledcSetup(0, 50, 10);  // 0ch 50 Hz 10bit resolution
    ledcAttachPin(SERVO, 0); // 15pin, 0ch
    ledcWrite(0,40);
}

void loop() {

    // Since fauxmoESP 2.0 the library uses the "compatibility" mode by
    // default, this means that it uses WiFiUdp class instead of AsyncUDP.
    // The later requires the Arduino Core for ESP8266 staging version
    // whilst the former works fine with current stable 2.3.0 version.
    // But, since it's not "async" anymore we have to manually poll for UDP
    // packets
    fauxmo.handle();

    static unsigned long last = millis();
    if (millis() - last > 5000) {
        last = millis();
        Serial.printf("[MAIN] Free heap: %d bytes\n", ESP.getFreeHeap());
    }

}

2 ESP32の接続例

スケッチにて指定したピンと電源とGNDのところに挿します。

f:id:kuracux:20180923224038p:plain:w300

3 Alexaアプリとの接続

前回の記事と同様に接続します。今回はボタンを押すとオン・オフに応じてサーボモータが指定した動きをします。

おわりに

ESP32とAlexaを連携して物理スイッチを制御する方法をご紹介しました。

かなり強引な方法ではありますが、音声やアプリから物理スイッチを制御できるようになると生活が便利になって良いですね。

おまけ

Amazon Echoのミュートボタンを音声でオンにする方法が分からなかったため、サーボモータを利用して音声操作で無理矢理押すようにしました。

ESP32をAmazon Alexaのスマートホームのデバイスに登録する方法

はじめに

ESP32とAmazon Alexa(以下、Alexa)の連携を考えた際にIFTTTとBlynkを利用する方法が最初に思いつきます。

qiita.com

qiita.com

しかしながら、IFTTTとAlexaの連携ではAmazon Echoに話しかける際に「◯◯、トリガー」と語尾にトリガーとつけて発話しなければなりません。

そこで本記事ではESP32をAlexaのスマートホームのデバイスにし、自然な発話から制御できる方法をご紹介します。

完成品

AlexaのアプリからLEDを制御しています。Amazon Echoに話しかけても同様のことが出来ます。


開発環境

準備物

  • ESP32-DevKitC

akizukidenshi.com

  • LEDと抵抗とブレッドボード(確認用)

前提

本記事ではESP32の開発環境の設定とAmazon Echo及びAlexaアプリの設定がお済みの方を対象としております。

1.FauxmoESPの取得

ESP32をスマートホームのデバイスとするライブラリであるFauxmoESPとライブラリ内で利用しているAsyncTCPを下記からダウンロードします。

FauxmoESPについてはバージョン2.4.4を利用しております。「ダウンロード」→「タグ」から2.4.4のzipファイルをダウンロードしてください。

bitbucket.org

github.com

ダウンロードしたものをArduino IDEの「スケッチ」→「ライブラリをインクルード」→「.ZIP形式のライブラリをインストール」を選択してインストールします。

Arduino IDEの「スケッチ」→「ライブラリをインクルード」→「ライブラリを管理」から「fauxmoESP」と検索すると同名のライブラリがありますが、ESP32は非対応のものです。

※※FauxmoESPのバージョン3.0.0については私の環境では正常に動作しませんでした。下記でも同様の指摘がされています。(2018/09/22)
xoseperez / fauxmoESP / issues / #58 - v3.0 not discovered by Alexa — Bitbucket

2.スケッチ例

Arduino IDEから下記のスケッチを書き込みます。こちらのスケッチはオンの時にLEDが点灯し、オフの時に消灯します。サンプル例をもとに作成してます。

#include <Arduino.h>
#include <WiFi.h>
#include "fauxmoESP.h"
#define SERIAL_BAUDRATE                 115200
#define LED                             2

fauxmoESP fauxmo;

char ssid[] = "";
char password[] = "";

// -----------------------------------------------------------------------------
// Wifi
// -----------------------------------------------------------------------------

void wifiSetup() {

    // Set WIFI module to STA mode
    WiFi.mode(WIFI_STA);

    // Connect
    Serial.printf("[WIFI] Connecting to %s ",ssid);
    WiFi.begin(ssid, password);

    // Wait
    while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(100);
    }
    Serial.println();

    // Connected!
    Serial.printf("[WIFI] STATION Mode, SSID: %s, IP address: %s\n", WiFi.SSID().c_str(), WiFi.localIP().toString().c_str());

}

void setup() {

    // Init serial port and clean garbage
    Serial.begin(SERIAL_BAUDRATE);
    Serial.println();
    Serial.println();

    // Wifi
    wifiSetup();

    // LED
    pinMode(LED, OUTPUT);
    digitalWrite(LED, HIGH);

    // You have to call enable(true) once you have a WiFi connection
    // You can enable or disable the library at any moment
    // Disabling it will prevent the devices from being discovered and switched
    fauxmo.enable(true);

    // Add virtual devices
    fauxmo.addDevice("照明");

    // fauxmoESP 2.0.0 has changed the callback signature to add the device_id,
    // this way it's easier to match devices to action without having to compare strings.
    fauxmo.onSetState([](unsigned char device_id, const char * device_name, bool state) {
        Serial.printf("[MAIN] Device #%d (%s) state: %s\n", device_id, device_name, state ? "ON" : "OFF");
        digitalWrite(LED, state);
    });

    // Callback to retrieve current state (for GetBinaryState queries)
    fauxmo.onGetState([](unsigned char device_id, const char * device_name) {
        return digitalRead(LED);
    });

}

void loop() {

    // Since fauxmoESP 2.0 the library uses the "compatibility" mode by
    // default, this means that it uses WiFiUdp class instead of AsyncUDP.
    // The later requires the Arduino Core for ESP8266 staging version
    // whilst the former works fine with current stable 2.3.0 version.
    // But, since it's not "async" anymore we have to manually poll for UDP
    // packets
    fauxmo.handle();

    static unsigned long last = millis();
    if (millis() - last > 5000) {
        last = millis();
        Serial.printf("[MAIN] Free heap: %d bytes\n", ESP.getFreeHeap());
    }

}

私の環境ではコンパイル時に\Arduino\libraries\xoseperez-fauxmoesp-985880034f3a\src\fauxmoESP.cppに対してエラーメッセージが2つ出ました。

  1. error: embedded '\0' in format [-Werror=format-contains-nul]
  2. error: format '%X' expects argument of type 'unsigned int', but argument 5 has type 'long unsigned int' [-Werror=format=]

該当している行はこちらの2つでした。

345行目:snprintf_P(uuid, sizeof(uuid), PSTR("%02X%06X46584D\0"), device_id, chip_id); // DEV_ID + CHIPID + "FXM"
350行目:sprintf(serial, "221703K0%06X\0", chip_id); // "221703K0" + CHIPID

1はこちらを参考にして修正をし、
stackoverflow.com

2は%Xを%lXと修正しました。

修正後はこちらとなります。

345行目:snprintf_P(uuid, sizeof(uuid), PSTR("%02X%06lX46584D%c"), device_id, chip_id,'\0'); // DEV_ID + CHIPID + "FXM"
350行目:sprintf(serial, "221703K0%06lX%c", chip_id,'\0'); // "221703K0" + CHIPID


修正後、再度コンパイルすることで、コンパイルエラーがなくなると思います。

3.ESP32の接続例

正常に動作しているかを確認するためにLEDを接続します。スケッチで指定したピン番号と同じ番号の箇所に繋ぎます。

f:id:kuracux:20180921232154j:plain

ESP32の起動後、Wi-Fiに接続できるとLEDが点灯します。

4.Alexaアプリと接続

Alexaアプリの「スマートホーム」→「デバイスを追加」を選択します。

f:id:kuracux:20180921233059j:plain:w250 f:id:kuracux:20180921233057j:plain:w250

Amazon Echoによる検索後、スケッチ例のfauxmo.addDeviceにて指定した名前が一覧に表示されます。

f:id:kuracux:20180921233111j:plain:w300

指定した名前を選択して、ボタンを押すとLEDが点灯・消灯します。また、Amazon Echoに「(指定した名前)を消して」や「(指定した名前)オン」と話しかけることで制御することも出来ます。

f:id:kuracux:20180921233121j:plain:w300

おわりに

ESP32をAlexaのスマートホームのデバイスに登録する方法をご紹介しました。

FauxmoESPのバージョン3.0.0では数値を扱えるようになるそうなので、実現できれば照明の調整等も出来そうですね。

This allows for a simpler code and also support for numeric values (you can now say "Alexa, set light to 50").

おまけ

ESP32を搭載しているM5Stackにおいても同様のことが出来ました。