2020年7月15日水曜日

インターフォンからSMSを送りXiaomi mi bandへ通知



耳が聞こえないとインターフォンが聞こえないのでsmart bandに通知を送りたい。

ずっと考えていましたが、小雨降るお散歩中に簡単な方法を思いついたので、作ってみました。構想半年、アイデア30分、実装1時間、ブログ2時間ってやつです。

なお、タイトルは途中経過を大幅に端折ってます。

実際には
  1. 呼び鈴を押す
  2. インターフォンの画面が明るくなる
  3. APDS9930で明るさを検知
  4. ESP32でIFTTTを叩く
  5. IFTTTが私のiPhoneにSMSを送る
  6. iPhoneが着信
  7. Xiaomi mi bandに着信通知
という流れです。

■SMSは有償です■

ところでSMSの送信は有償です。今回使うclicksend.comだと1回約5円です。clicksend.comのアカウントを取得すると100円分のチャージが7日間使えます。実験であればそれで試せます。それでイケるとなったらカード番号など登録しましょう。

なんで自分ちのインターフォンが有償なんじゃい?!という気持ちがないではないですが、まぁ聴覚障害者として生まれちゃったのでしょうがないですね。

我が家の場合、比較的単価の安い荷物はみんな宅配ボックス、そうでない荷物や書留などについては電話で呼び出してもらってます。残りは生協ぐらいですが、生協は対面で受け取ると保冷ボックスが不要で手間がかからないというメリットがあって、それはまぁ5円に見合うのではないかと思っています。

■必要資材■


■IFTTTの設定■

アカウントのとり方などは他の方のブログを参考にしてください。以下の手順でIFTTTにサービスを追加します……「サービス」であってます?呼び方がわからん。
  1. ブラウザでHOME画面の右上、Createをクリック
  2. 「If」の後の「+」をクリック
  3. Search Servicesで「Webhook」と入力し「Webhooks」をクリック
    WebhooksはIFTTTの特定のURLを叩くと起動します。ESP32からのアクセスにうってつけですね。
  4. 「Receive a web request」をクリック
  5. 「Event Name」を入力します。今回は画面の明かりが点灯したことをトリガーにするので「light_up」と入力し、create triggerボタンをクリックします。
  6. If Thenのあとの「+」をクリック
  7. ClickSend SMSを選びます。
  8. 青い「Send SMS」をクリックします。
  9. Toにスマフォの電話番号を入力してCreate actionをクリックします。
  10. Finishをクリックします。
と、すみません。6-10のどこかでclicksend.comのアカウント取得画面に飛ぶのですが、スクショ取りそこねてしまいました。特に難しいことはないと思います。

ともあれ、これで特定のURLを叩くとSMSに通知が飛ぶ、というサービスができました。試すには
  1. ブラウザ上でIFTTTのHomeに戻る。
  2. Webhooksをクリック
  3. 右上のDocumentationをクリック
  4. 「Make a POST or GET web request to:」下の{event}にlight_upと入力
  5. value1, value2, value3には適当な文字列などを入れてみる。
    入力するとそれにつれてcurlのパラメータが変わっていきます。
  6. Test itのボタンをクリック
数秒後にさっきToで登録した電話番号にSMSが届きます。

ここでcurlの-d以降の部分をhttp postすれば中身がメッセージとして送られますが、 今回の用途ではSMSだけ送ればいいのでhttps以降だけを叩くのが簡単です。今回もそれで済ませてます。ごめんなさい。

■ハードウェアの接続■

私は以下のブログを参考にしました。ってわしのブログや。どんなつまらないことでもブログに残しておくべきだなぁとしみじみ思う今日このごろです。

CJMCU-9930ESP32
VL3.3v
GNDGND
VCC3.3v
SCL22
SDA21

ブログと異なり、INT - 2の配線は不要です。

■ESP32の実装■

APDS9930のサンプルプログラムを元に、http secureのサンプルを切り貼りしました。コピペエンジニアリングです。ごめんなさい。
//
//  WiFi Secure, IFTTT
//

#include <WiFiClientSecure.h>

#define ssid     "....ssid...."
#define password "....password...."

const char*  server = "maker.ifttt.com";  // Server URL

const char* test_root_ca = \
 "-----BEGIN CERTIFICATE-----\n" \
"MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n" \
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \
"DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n" \
"SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n" \
"GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n" \
"AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n" \
"q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n" \
"SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n" \
"Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n" \
"a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n" \
"/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n" \
"AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n" \
"CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n" \
"bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n" \
"c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n" \
"VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n" \
"ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n" \
"MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n" \
"Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n" \
"AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n" \
"uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n" \
"wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n" \
"X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n" \
"PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n" \
"KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n" \
"-----END CERTIFICATE-----\n";

WiFiClientSecure client;

void submit() {
  Serial.println("\nStarting connection to server...");
  if (!client.connect(server, 443))
    Serial.println("Connection failed!");
  else {
    Serial.println("Connected to server!");
    // Make a HTTP request:
    client.println("POST https://maker.ifttt.com/trigger/light_up/with/key/....api key.... HTTP/1.0");
    client.println("Host: maker.ifttt.com");
    client.println("Connection: close");
    client.println();

    while (client.connected()) {
      String line = client.readStringUntil('\n');
      if (line == "\r") {
        Serial.println("headers received");
        break;
      }
    }
    while (client.available()) {
      char c = client.read();
      Serial.write(c);
    }

    client.stop();
  }
}


//
//  APDS9930
//

#include <Wire.h>
#include <APDS9930.h>

// Global Variables
APDS9930 apds = APDS9930();
float ambient_light = 0; // can also be an unsigned long
uint16_t ch0 = 0;
uint16_t ch1 = 1;



//
//  setup
//

void setup() {
  // Initialize Serial port
  Serial.begin(115200);

  Serial.print("Attempting to connect to SSID: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  // attempt to connect to Wifi network:
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    // wait 1 second for re-trying
    delay(1000);
  }

  Serial.print("Connected to ");
  Serial.println(ssid);

  // Initialize APDS-9930 (configure I2C and initial values)
  if ( apds.init() ) {
    Serial.println(F("APDS-9930 initialization complete"));
  } else {
    Serial.println(F("Something went wrong during APDS-9930 init!"));
  }

  // Start running the APDS-9930 light sensor (no interrupts)
  if ( apds.enableLightSensor(false) ) {
    Serial.println(F("Light sensor is now running"));
  } else {
    Serial.println(F("Something went wrong during light sensor init!"));
  }

  delay(500);
}


//
//  loop
//
uint32_t prevMillis = 0;

void loop() {

  // Read the light levels (ambient)
  if (  !apds.readAmbientLightLux(ambient_light)) {
    Serial.println(F("Error reading light values"));
  } else {
    Serial.print(F("Ambient: "));
    Serial.println(ambient_light);

    uint32_t thisMillis = millis();
    if ((prevMillis == 0 || thisMillis - prevMillis > 180 * 1000) && ambient_light > 50) {

      submit();

      prevMillis = thisMillis;
    }

    //    char fstr[16];
    //    dtostrf(ambient_light, 5, 1, fstr);
    //    M5.Lcd.drawString(fstr, 80,  70);
  }

  delay(100);
}

2 件のコメント:

  1. ちょいちょい小ネタ挟んでて笑ってしまいます
    (笑)。
    ぎんてん

    返信削除
    返信
    1. ありがとうございます。むしろネタがメインなもので、嬉しいです ^ ^

      削除

注: コメントを投稿できるのは、このブログのメンバーだけです。