文章程式碼顯示

2018年1月26日 星期五

NodeMCU 教學 - 04:WeMos D1 mini (NodeMCU) 與 Line 的連結 (實際應用於居家監控)



NodeMCU 教學 - 03:WeMos D1 mini (NodeMCU) 與 Line 的連結

我們有提到使用微控器來發 Line 的通知,在本文中我想更形象化學會這個能做怎樣的應用

一個簡單的例子是我們使用「微動開關」來做大門開啟 or 關閉的監測

各位可以回想一下在賣場的門窗保全是怎樣一回事,事實上在賣場的門窗的窗框旁邊都會看到一個「磁性開關」,它的原理跟微動開關一模一樣,只是它改成非接觸型而已

我手邊沒有這樣的磁性開關(買一個也挺便宜的,大概50元就能解決)

所以就用微動開關來做為演示


我在 IFTTT 上面設定了兩個不同的"事件"

分別代表大門被開啟的 doorOpen 以及大門關閉的 doorClose

並且發送對應的 Message 。此部分的設定請參考

NodeMCU 教學 - 03:WeMos D1 mini (NodeMCU) 與 Line 的連結


透過瀏覽器 URL 觸發兩個"事件"的方式,我們可以讓 IFTTT 的 Line 機器人發送兩條不同的通知給我們。

後記補充:我發現 IFTTT 內的 value1 等等 可以傳送文字(中英文皆可),所以我們並不需要拆成 doorClose 、 doorOpen 兩個事件來使用,只要在傳送 URL 的地方直接傳送不同的字串就可以了

順帶一提,每個 Line 帳戶在 IFTTT 上的 KEY 是唯一的,藉由改不同的 "event" 來發送不同的通知。

上面我們用瀏覽器確定可以觸發兩條不同的通知後,我們就延續上一章的程式碼,稍微改動一下就可以了

#include "ESP8266WiFi.h"
#include "SimpleTimer.h"

void send_event(const char *event); // Function 原型

// ===== Wifi setup =====
const char *ssid     = “WIFI名稱";
const char *password = “WIFI密碼";

// ===== IFTTT setup =====
const char *host = "maker.ifttt.com";
const char *privateKey = “IFTTT 的 KEY";

// ===== Hardware setup =====
const int buttonPin = D8; //我們假設當大門關起來的時候buttonPin為LOW
const int ledPin = D4;       

// ===== Variables=====
volatile bool doorState_last = LOW; 

SimpleTimer timer; 

/* =====================*/
// ===== timer_2000 ====
/* 2000 毫秒定時器中斷 */
/* =====================*/
void timer_2000(){
  if( digitalRead(buttonPin) != doorState_last )
  {
    Serial.println("doorState changed !!!");
    
    if( digitalRead(buttonPin) ) { Serial.println(" ========== The door is Opening ========== "); send_event("doorOpen"); }
      else  { Serial.println(" ========== The door is Closing ========== "); send_event("doorClose");  }
     
    doorState_last = digitalRead(buttonPin);
  }
}

/* =====================*/
// ======== setup =======
/* =====================*/
void setup() 
{
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(115200);
  delay(10);

  // ===== We start by connecting to a WiFi network =====
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  // ===== Wait for the connection, flashing the LED while we wait =====
  int led = HIGH;  
  while (WiFi.status() != WL_CONNECTED) {
    delay(200);
    digitalWrite(ledPin, led);
    led = !led;
    Serial.print(".");
  }
  digitalWrite(ledPin, LOW);

  // ===== Connect successful =====
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  timer.setInterval(2000L, timer_2000);
}

/* =====================*/
// ======== loop =======
/* =====================*/
void loop() 
{
  timer.run(); 
}

/* =====================*/
// ===== send_event ====
/* =====================*/
void send_event(const char *event)
{
  digitalWrite(ledPin,HIGH);
  Serial.print("Connecting to ");
  Serial.println(host);
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("Connection failed");
    return;
  }
  
  // Create a URI for the request
  String url = "/trigger/";
  url += event;
  url += "/with/key/";
  url += privateKey;
  
  //Serial.print("Requesting URL: ");
  //Serial.println(url);
  
  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");

  // Read all the lines of the reply from server and print them to Serial,
  // the connection will close when the server has sent all the data.
  while(client.connected())
  {
    if(client.available())
    {
      String line = client.readStringUntil('\r');
      Serial.print(line);
    } else {
      // No data yet, wait a bit
      delay(50);
    };
  }
  
  Serial.println();
  Serial.println("closing connection");
  client.stop();
  digitalWrite(ledPin, LOW);
}


這邊有使用到另一個函式庫 SimpleTimer (下載)

每兩秒觸發一次 timer_2000 中斷函式,用來檢測開關狀態。當開關狀態有改變的情況下就會觸發對應的"事件",我的微動開關在沒有被按下的時候是 HIGH 訊號;按下是 LOW ,若你的開關邏輯與我不同就只要把程式碼判斷開關狀態的部分顛倒過來就好。

我拍了一段影片來展示結果


連結在此



學會了這個之後我們就可以做很多變化,甚至程式碼完全不用進行修改。

我有想到幾個實用的應用,供各位參考
  1. 放置在家中不同樓層,例如你媽在 1 樓煮飯要叫在 3 樓的你
  2. 放置在家中浴室當做老人的緊急通知警報使用
  3. 放在戶外陽台用來偵測有沒有下雨,提醒你該收衣服了
  4. 放在門外換成人體感測器
  5. 配合電流感測器,監測儲水式熱水器有沒有關
  6. 監測你家的寵物有沒有從圍欄裡脫逃,正在玩你家的垃圾桶 .....
  7. 配合電流感測器,監測你兒子有沒有半夜起來玩電腦

隨便想想就能做很多有趣又實用的應用,待各位自行發揮創意了 !!!


↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引