Setup IKEA VINDRIKTNING + WeMos D1 mini (Tasmota Firmware)

IKEA VINDRIKTNING + WeMos D1 mini (Tasmota Firmware)

IoT 101 ของเรา วันนี้ จะมาพูดถึงวิธีการ Setup IKEA VINDRIKTNING + WeMos D1 mini (Tasmota Firmware) กันครับ
โดยมีขั้นตอนต่างๆ ประมาณนี้

1. เกาะ WiFi (AP): tasmota-XXXXXX-XXXX

2. เปิด Web Browser เข้า http://192.168.4.1

3. ทำการ Setup WiFi ที่ต้องการใช้งาน

4. จากนั้นเข้าผ่าน IP ใหม่ ของ Tasmota ที่ได้จาก WiFi ที่คุณใช้งาน

5. คลิก Configuration > Configure Module เลือก Generic (0) กด Save แล้วรอ Tasmota Restart

6. คลิกเข้า Configure Module อีกครั้ง
– PIN: D1 GPIO5 เลือก VINDRIKTNING
– PIN: D6 GPIO12 เลือก DHT11
กด Save แล้วรอ Tasmota Restart

7. เมื่อเรา config ถูกต้อง ก็จะได้ค่า Temperature, Humidity, Dew point และ PM 2.5 ตามรูปครับ

8. คลิก Configuration > Configure MQTT
– Host: mqtt.tono.tech
– Port: 1883
– Client: DVES_%06X (ค่า default)
– User: mqtt
– Password: XXXXXX
– Topic: tasmota_%06X (ค่า default)
* จากตัวอย่าง จะได้ค่า tasmota_1AB59B ตามเลข MAC Address ของตัว ESP8266
– Full Topic: %prefix%/%topic%/ (ค่า default)
กด Save แล้วรอ Tasmota Restart

9. คลิก Console จะเห็น Logs ที่ Tasmota ประมาณนี้ เป็นอันใช้ได้แล้ว

07:48:21.453 MQT: tele/tasmota_1AB59B/SENSOR = {"Time":"2023-03-21T07:48:21","DHT11":{"Temperature":24.7,"Humidity":72.0,"DewPoint":19.3},"VINDRIKTNING":{"PM2.5":7},"TempUnit":"C"}

10. Download IoT MQTT Panel จาก Play Store

11. เลือก Backup and Restore
จากนั้นเลือก RESTORE จาก pm25dashboard.json นี้ หรือจะเลือกสร้าง Dashboard ใหม่เองก็ได้
เปลี่ยนชื่อ topic เป์นของ Tasmota Device ของเรา
อย่างเช่นของผมจะเป็น tele/tasmota_1AB59B/SENSOR

pm25dashboard.json

{"dataVersion":120,"globalSettings":{"runInBackground":true,"appTheme":"dark"},"connections":[{"connectionName":"Tasmota PM2.5","clientId":"ub5bvpTlZA","host":"mqtt.tono.tech","port":1883,"connectionType":"tcp","username":"mqtt","password":"XXXXXX","connectionTimeout":30,"keepAlive":60,"autoConnect":true,"disableHostnameCheck":false,"caCertificateFileName":"","clientCertificateFileName":"","clientKeyFileName":"","sslClientPassword":"","enableWillMessage":false,"willTopic":"","willPayload":"","willRetain":false,"willQoS":0,"defaultDashboard":"dashboard_0","connectionId":"connection_0","notifyOnDisconnect":false}],"dashboards":[{"connectionId":"connection_0","dashboardId":"dashboard_0","dashboardName":"PM 2.5","dashboardPrefixTopic":"","lockPanels":true}],"panels":[{"connectionId":"connection_0","dashboardId":"dashboard_0","panelId":"panel_7","panelName":"WiFi Signal","type":"progress","mqttType":"sub","topic":"tele\/tasmota_1AB59B\/STATE","payloadMin":0,"payloadMax":100,"qos":0,"defaultColor":"success","dynamicColor":true,"firstColor":"danger","secondColor":"warning","thirdColor":"success","firstColorEnd":50,"secondColorEnd":80,"disableDashboardPrefix":true,"panelWidth":"100","panelMergeClass":"","showReceivedTimeStamp":true,"unit":"%","orientation":"horizontal","enableNotification":false,"notificationFilter":"all","notificationMin":"","notificationMax":"","notificationValue":"","notificationRegex":"","notificationMessage":"","isJSONPayload":true,"jsonPath":"$.Wifi.RSSI","messageFactor":1,"step":1},{"connectionId":"connection_0","dashboardId":"dashboard_0","panelId":"panel_1","panelName":"Temp","type":"gauge","mqttType":"sub","topic":"tele\/tasmota_1AB59B\/SENSOR","payloadMin":0,"payloadMax":100,"qos":0,"disableDashboardPrefix":false,"panelWidth":"33","firstColor":"#009600","secondColor":"#fac800","thirdColor":"#ff5722","firstColorEnd":33.33,"secondColorEnd":66.67,"panelMergeClass":"","showReceivedTimeStamp":false,"unit":"°C","enableNotification":false,"notificationFilter":"all","notificationMin":"","notificationMax":"","notificationValue":"","notificationRegex":"","notificationMessage":"","isJSONPayload":true,"jsonPath":"$.DHT11.Temperature","messageFactor":"","step":1},{"connectionId":"connection_0","dashboardId":"dashboard_0","panelId":"panel_2","panelName":"Humidity","type":"gauge","mqttType":"sub","topic":"tele\/tasmota_1AB59B\/SENSOR","payloadMin":0,"payloadMax":100,"qos":0,"disableDashboardPrefix":false,"panelWidth":"33","firstColor":"#009600","secondColor":"#fac800","thirdColor":"#ff5722","firstColorEnd":70,"secondColorEnd":100,"panelMergeClass":"","showReceivedTimeStamp":false,"unit":"%","enableNotification":false,"notificationFilter":"all","notificationMin":"","notificationMax":"","notificationValue":"","notificationRegex":"","notificationMessage":"","isJSONPayload":true,"jsonPath":"$.DHT11.Humidity","messageFactor":1,"step":1},{"connectionId":"connection_0","dashboardId":"dashboard_0","panelId":"panel_3","panelName":"PM 2.5","type":"gauge","mqttType":"sub","topic":"tele\/tasmota_1AB59B\/SENSOR","payloadMin":0,"payloadMax":1000,"qos":0,"disableDashboardPrefix":false,"panelWidth":"33","firstColor":"#009600","secondColor":"#fac800","thirdColor":"#ff5722","firstColorEnd":35,"secondColorEnd":85,"panelMergeClass":"","showReceivedTimeStamp":false,"unit":"ug\/m3","enableNotification":false,"notificationFilter":"all","notificationMin":"","notificationMax":"","notificationValue":"","notificationRegex":"","notificationMessage":"","isJSONPayload":true,"jsonPath":"$.VINDRIKTNING.['PM2.5']","messageFactor":1,"step":10},{"connectionId":"connection_0","dashboardId":"dashboard_0","panelId":"panel_0","panelName":"PM 2.5","type":"line-graph","mqttType":"sub","qos":0,"comboItemList":[{"topic":"tele\/tasmota_1AB59B\/SENSOR","label":"ug\/m3","color":"#7b00f5","showArea":true,"showPoints":true,"unit":"","enableNotification":false,"notificationFilter":"all","notificationMin":"","notificationMax":"","notificationValue":"","notificationRegex":"","notificationMessage":"","isJSONPayload":true,"jsonPath":"$.VINDRIKTNING.['PM2.5']","messageFactor":1}],"disableDashboardPrefix":false,"panelWidth":"100","panelMergeClass":"","maxPersistence":50,"smoothCurve":true},{"connectionId":"connection_0","dashboardId":"dashboard_0","panelId":"panel_4","panelName":"Temp","type":"line-graph","mqttType":"sub","qos":0,"comboItemList":[{"topic":"tele\/tasmota_1AB59B\/SENSOR","label":"°C","color":"#99ff99","showArea":true,"showPoints":true,"unit":"°C","enableNotification":false,"notificationFilter":"all","notificationMin":"","notificationMax":"","notificationValue":"","notificationRegex":"","notificationMessage":"","isJSONPayload":true,"jsonPath":"$.DHT11.Temperature","messageFactor":1}],"disableDashboardPrefix":false,"panelWidth":"100","panelMergeClass":"","maxPersistence":50,"smoothCurve":true},{"connectionId":"connection_0","dashboardId":"dashboard_0","panelId":"panel_5","panelName":"Humidity ","type":"line-graph","mqttType":"sub","qos":0,"comboItemList":[{"topic":"tele\/tasmota_1AB59B\/SENSOR","label":"%","color":"#007bf5","showArea":true,"showPoints":true,"unit":"%","enableNotification":false,"notificationFilter":"all","notificationMin":"","notificationMax":"","notificationValue":"","notificationRegex":"","notificationMessage":"","isJSONPayload":true,"jsonPath":"$.DHT11.Humidity","messageFactor":1}],"disableDashboardPrefix":false,"panelWidth":"100","panelMergeClass":"","maxPersistence":50,"smoothCurve":true}]}

12. ถ้าเสร็จเรียบร้อย เราก็จะได้ Dashboard ไว้ใช้งานแล้วครับ

PM 2.5 Dashboard

* เพิ่มเติมครับ วิธีการ Hard Reset Tasmota กลับไปเป็นค่า default

1. ถอดสาย USB ออก 30s
2. เสียบสาย ถอดสาย สลับกัน 7 ครั้ง (ครั้งละไม่เกิน 5s)

เป็นอย่างไรกันบ้างครับ ไม่ยากเลยใช่ไหมครับ ในการทำ Dashboard ดีๆ ไว้ดูคุณภาพอากาศ สำหรับช่วง PM 2.5 ประเทศเรา เป็นผู้นำอันดับโลก แบบนี้ 🙂
ถ้าสงสัยหรืออยากสอบถามเพิ่มเติม comment ไว้ตรงนี้ หรือ add LINE ID: pornpasok เข้ามาพูดคุยกันได้ครับ ..

LINE Bot + node.js + MQTT + ESP32 (IoT) เปิด/ปิด ไฟ (ตอนที่ 2)

สวัสดีครับ จากตอนที่แล้ว ที่ผมพูดถึงรายละเอียดต่างๆ ที่จะใช้ในการทำ ระบบเปิด/ปิด ไฟ
ว่าต้องใช้อะไรบ้าง วันนี้ จะมาลงรายละเอียด ในแต่ละส่วนกันครับ ..
อ่านตอนที่ 1 ได้ที่ LINE Bot + node.js + MQTT + ESP32 (IoT) เปิด/ปิด ไฟ (ตอนที่ 1)

การทำงานคือ ผมจะสามารถสั่ง ให้บอท (LINE Messaging API) สั่งเปิด/ปิดไฟ ได้ผ่าน การ chat ดังภาพ

0.ความรู้ที่ต้องมี ในบทความนี้

– การใช้งาน Arduino IDE เบื้องต้น
– การเขียน node.js เบื้องต้น
– การใช้งาน LINE Messaging API เบื้องต้น
– การใช้งาน Git เบื้องต้น

1.เตรียมอุปกรณ์


สำหรับบอร์ด ESP32 ที่ผมจะใช้ในการทดลองนี้ จะเป็น Node32 Lite นะครับ สามารถหาซื้อได้ที่นี่ครับ ราคา 275 บาท
https://www.gravitechthai.com/product-detail.php?WP=pQugZKpmGQAgG2rDqYyc4Uuw

ปล.หรือถ้าเพื่อนๆ มีบอร์ดอื่นๆ เช่น ESP8266, NodeMCU อยู่แล้ว ก็สามารถใช้งานได้เหมือนกันครับ

2.สมัครใช้บริการ LINE Messaging API


LINE Developers

ตรงส่วนวิธีการสมัครใช้งาน LINE Messaging API มีหลายๆ ท่านเขียนบทความไว้แล้ว ตัวอย่างเช่น

LINE Bot 101 — จับมือทำบอท ของคุณ Sitthi Thiammekha (LINE API Expert)

สร้าง LINE Bot ด้วย Node.js + Messaging API — A Beginner’s Guide ของคุณ Ingkwan

3.สมัครใช้บริการ Heroku สำหรับ CloudMQTT Server


Heroku.com

เมื่อกรอกรายละเอียดการสมัครเสร็จแล้ว เราจะเข้าสู่ Dashboard ของ Heroku ครับ


– ที่หน้า Dashboard เลือก New > Create new app


– ตั้งชื่อ App ของเรา ในที่นี้ผมตั้งชื่อ esp32-mqtt

ถ้าสร้างสำเร็จ เราจะเข้าหน้าแรก ของ App เราได้ละ อย่างของผมจะเป็น
https://esp32-mqtt.herokuapp.com/


– ที่ Resources เลือก Find more add-ons


– เลือก CloudMQTT


– เลือก Install CloudMQTT


– เลือก App ที่จะ Install CloudMQTT ในที่นี้ ของผมคือ esp32-mqtt


– เลือก Provision add-on


– เสร็จแล้วจะได้ดังนี้ ให้เราคลิกเพื่อดูรายละเอียดของ CloudMQTT ของเราได้ที่ menu ด้านล่าง


– ค่า config CloudMQTT ตรงนี้ เดี๋ยวเราจะใช้กับ webhook ที่เป็น node.js ของเรานะครับ

4.LINE Bot API Code (node.js)

File หลักๆ ที่เราจะใช้ ในการ Deploy ขึ้น Heroku App ของเรา มี 2 file ครับคือ
Procfile (ไม่ต้องมี .txt) นะ ใช้สำหรับบอกว่า ให้ App เราทำงานแบบไหน เรียก file ไหน
index.js เป็น file หลัก ของ LINE Bot API เราครับ

จากนั้น เรามาดูที่ code ที่เป็น LINE Bot API กันครับ
ส่วนที่เราจะต้องแก้ไข หลักๆ มีด้วยกัน 3 จุดครับคือ

CH_ACCESS_TOKEN คือค่า ยาวๆ ที่เราได้จาก Channel access token (long-lived) ของ Messaging API
mqtt_host คือค่าที่เราได้จาก CloudMQTT บน Heroku
options คือค่าต่างๆ ที่เราได้จาก CloudMQTT บน Heroku เช่นกันครับ

Code LINE Bot API ที่เป็น node.js สำหรับ Deploy ขึ้น Heroku ของเราครับ
ใครที่เขียน code คล่องๆ แก้ไข ให้ code สวยงาม กระชับกว่านี้ได้นะครับ อันนี้ผมเขียนแบบด่วนๆ มาก 🙁

Procfile

web: node index.js

 

index.js

var express = require('express')
var bodyParser = require('body-parser')
var request = require('request')
var app = express()

var mqtt = require('mqtt');

// Your Channel access token (long-lived) 
const CH_ACCESS_TOKEN = '';

// MQTT Host
var mqtt_host = 'mqtt://m15.cloudmqtt.com';

// MQTT Topic
var mqtt_topic = '/ESP32';

// MQTT Config
var options = {
    port: 15443,
    host: 'mqtt://m15.cloudmqtt.com',
    clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),
    username: 'mqttuser',
    password: 'mqttpass',
    keepalive: 60,
    reconnectPeriod: 1000,
    protocolId: 'MQIsdp',
    protocolVersion: 3,
    clean: true,
    encoding: 'utf8'
};


app.use(bodyParser.json())

app.set('port', (process.env.PORT || 4000))
app.use(bodyParser.urlencoded({extended: true}))
app.use(bodyParser.json())

app.post('/webhook', (req, res) => {
  var text = req.body.events[0].message.text.toLowerCase()
  var sender = req.body.events[0].source.userId
  var replyToken = req.body.events[0].replyToken
  console.log(text, sender, replyToken)
  console.log(typeof sender, typeof text)
  // console.log(req.body.events[0])

  if (text === 'info' || text === 'รายงาน') {
    // Info
    inFo(sender, text)
  }
  else if (text === '1' || text === 'เปิด' || text === 'on') {
    // LED On
    ledOn(sender, text)
  }
  else if (text === '0' || text === 'ปิด' || text === 'off') {
    // LED Off
    ledOff(sender, text)
  }
  else {
    // Other
    sendText(sender, text);
  }

  res.sendStatus(200)
})

function sendText (sender, text) {
  let data = {
    to: sender,
    messages: [
      {
        type: 'text',
        text: 'กรุณาพิมพ์ : info | on | off | เปิด | ปิด เท่านั้น'
      }
    ]
  }
  request({
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer '+CH_ACCESS_TOKEN+''
    },
    url: 'https://api.line.me/v2/bot/message/push',
    method: 'POST',
    body: data,
    json: true
  }, function (err, res, body) {
    if (err) console.log('error')
    if (res) console.log('success')
    if (body) console.log(body)
  })
}

function inFo (sender, text) {
  let data = {
    to: sender,
    messages: [
      {
        type: 'text',
        text: 'uid: '+sender
      }
    ]
  }
  request({
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer '+CH_ACCESS_TOKEN+''
    },
    url: 'https://api.line.me/v2/bot/message/push',
    method: 'POST',
    body: data,
    json: true
  }, function (err, res, body) {
    if (err) console.log('error')
    if (res) console.log('success')
    if (body) console.log(body)
  })
}


function ledOn (sender, text) {
  var client = mqtt.connect(mqtt_host, options);
  client.on('connect', function() { // When connected
      console.log('MQTT connected');
      // subscribe to a topic
      client.subscribe(mqtt_topic, function() {
          // when a message arrives, do something with it
          client.on('message', function(topic, message, packet) {
              console.log("Received '" + message + "' on '" + topic + "'");
          });
      });
      

      // publish a message to a topic
      client.publish(mqtt_topic, 'on', function() {
          console.log("Message is published");
          client.end(); // Close the connection when published
      });
      
  });
    

  let data = {
    to: sender,
    messages: [
      {
        type: 'text',
        text: 'LED ON'
      }
    ]
  }
  request({
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer '+CH_ACCESS_TOKEN+''
    },
    url: 'https://api.line.me/v2/bot/message/push',
    method: 'POST',
    body: data,
    json: true
  }, function (err, res, body) {
    if (err) console.log('error')
    if (res) console.log('success')
    if (body) console.log(body)
  })
}

function ledOff (sender, text) {
  var client = mqtt.connect(mqtt_host, options);
  client.on('connect', function() { // When connected
      console.log('MQTT connected');
      // subscribe to a topic
      client.subscribe(mqtt_topic, function() {
          // when a message arrives, do something with it
          client.on('message', function(topic, message, packet) {
              console.log("Received '" + message + "' on '" + topic + "'");
          });
      });
      

      // publish a message to a topic
      client.publish(mqtt_topic, 'off', function() {
          console.log("Message is published");
          client.end(); // Close the connection when published
      });
      
  });

  let data = {
    to: sender,
    messages: [
      {
        type: 'text',
        text: 'LED OFF'
      }
    ]
  }
  request({
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer '+CH_ACCESS_TOKEN+''
    },
    url: 'https://api.line.me/v2/bot/message/push',
    method: 'POST',
    body: data,
    json: true
  }, function (err, res, body) {
    if (err) console.log('error')
    if (res) console.log('success')
    if (body) console.log(body)
  })
}

app.listen(app.get('port'), function () {
  console.log('run at port', app.get('port'))
})


– CH_ACCESS_TOKEN คือค่ายาวๆ ตรงนี้แหละครับ


– mqtt_host กับ options คือค่าที่ได้จาก CloudMQTT ตรงนี้ครับ

5.Deploy Webhook API code ขึ้น Heroku

จาก Step 3 ที่เราสร้าง App ของเราไว้ อย่างของผมจะชื่อ esp32-mqtt ให้เราเข้ามาที่ Deploy

– อันดับแรกเลย ถ้าเรายังไม่เคยใช้ Heroku ให้ Download และ Install Heroku CLI กันก่อนที่
Download and install the Heroku CLI


– หลังจากลง Heruku CLI เสร็จแล้ว ที่ Terminal พิมพ์ heroku login


– ตัว Browser จะเด้งหน้า Heroku Login ขึ้นมา ให้เราทำการ Login ให้เรียบร้อย


– เมื่อเรา Login สำเร็จแล้ว ก็จะเข้าสู่ขั้นตอนถัดไป ที่ Terminal (CLI)

ทำการสร้าง Git repository

cd my-project/
git init
heroku git:remote -a esp32-mqtt

ทดลอง Deploy

git add .
git commit -am "make it better"
git push heroku master

จากนั้น สร้าง file จาก Step 4 คือ Procfile กับ index.js ที่ Directory ที่สร้างขึ้น อย่างของผมจะเป็น esp32-mqtt

จากนั้น install module ที่จำเป็น ที่เราใช้ในการเขียน App ของเรา ดังนี้

npm init
npm install express --save
npm install request --save
npm install mqtt --save

เราจะได้ file ต่างๆ เพิ่มเข้ามา ใน directory ของเรา

ทดลอง run Wehhook API ที่เราเขียน ด้วย node.js ค่า default จะเป็น port 4000
node index.js

เข้าผ่าน localhost:4000 จะได้ดังรูป Error ไม่เป็นไรครับ ถือว่าทำงานได้แล้ว เพราะเราไม่รับ GET

ทำการ Deploy code จริง ขึ้น Heroku

git add .
git commit -am "add Procfile index.js"
git push heroku master

จากนั้นลองเข้า App ของเราผ่าน URL ที่เราทำการตั้งไว้ อย่างของผมจะเป็น
https://esp32-mqtt.herokuapp.com/

หน้าจะจะได้แบบนี้ ไม่ต้องตกใจครับ เพราะเราไม่รับ GET
แต่ถ้าไม่ได้ ให้เราลองใช้ CLI ดู logs ว่าผิดพลาดตรงไหน

heroku logs --tail

เสร็จแล้วครับ LINE Bot API (webhook) ของเรา บน Heroku .. 🙂

6.Config Webhook API ของเราเข้ากับ LINE Messaging API

มาถึงขั้นตอนสุดท้ายในส่วนของ Webhook API ของเรากันแล้วครับ นั่นคือ การผูกกับ LINE Messaging API

– ขั้นตอนแรก เราต้องไป Use webhooks ให้ Enabled แล้ว Save ก่อนนะครับ ตกม้าตาย ตรงนี้กันมาเยอะแล้ว 🙁
– จากนั้น ใส่ URL ของ App เรา ที่ได้จาก Heroku แล้วตามด้วย /webhook ครับ อย่างของผมก็จะเป็น
https://esp32-mqtt.herokuapp.com/webhook
– จากนั้น กด Verify ดูครับ ถ้าไม่มีอะไรผิดพลาด ก็จะ Success ครับ 🙂


– ประมาณนี้ ก็เป็นอันว่า เรียบร้อยแล้วครับ LINE Messaging API กับ Webhook บน Heroku เราใช้งานได้แล้ว 🙂

7.เขียน code Arduino ให้กับ Node32 Lite

ดูวิธีการติตตั้งบอร์ดใหม่ๆ (Node32 Lite) เข้าไปใน Arduino IDE ได้ที่นี่ครับ
http://www.ayarafun.com/2018/12/how-to-setup-lamloei-32-lite-with-arduino/

เลือกชนิดของ Board ที่เราใช้ให้ถูกต้อง แล้วทำการ Verify และ Upload Code โลดครับ ..

– ในที่นี้ผมใช้บอร์ด Node32 Lite จะต้องเลือกเป็น Node32s รุ่นพี่มันครับ 🙂

ตัว Arduino IDE ให้เราทำการ add Library PubSubClient กับ WiFiManager เข้าไปด้วยครับ


– ไปที่ Tools > Manage Libraries…


Manage Libraries…


– Add Lib PubSubClient


– Add Lib WiFiManager

สำหรับ code จะมี 2 แบบ คือ

แบบ ที่ 1 fix SSID กับ password ไปใน code เลย แบบนี้จะดี ตรงที่เราไม่ต้องมา config ให้บอร์ดเราไปเกาะ WiFi อีกรอบ เหมาะสำหรับการทดลอง หรือใช้ SSID เดิมตลอด ..


– ถ้าเราดูจาก Serial Monitor จะเห็นรายละเอียดการ connect แบบ fix SSID ดังนี้

แบบ ที่ 2 ใช้ WiFiManager คือจะสามารถ config ให้ Node32 Lite ของเราไปเกาะ SSID (AP) ตัวที่เราต้องการได้ อันนี้จะสะดวก เวลาไปใช้งานจริง ไม่ต้อง Upload code เข้าไปใหม่


– วิธีการ config ด้วย WiFiManager หลังจาก Upload Code เสร็จ ให้เราไปเกาะ SSID ชื่อ ESP32_xxxxxx จะขึ้นหน้า menu config ดังรูป


– จากนั้นเลือก SSID(AP) ที่เราต้องการจะให้ไปเกาะ ใส่ password แล้วกด Save


– ถ้าเราดูจาก Serial Monitor จะเห็นรายละเอียดการ connect แบบใช้ WiFiManager ดังนี้

มาดูในส่วนของ Code กันครับ

Code แบบที่ 1 fix SSID กับ password ใน code

#include <PubSubClient.h>
#include <WiFi.h>

// Update these with values suitable for your network.
const char* ssid = "tonofarm.io"; // AP Name
const char* password = "********"; // AP Password

// Config MQTT Server
#define mqtt_server "m15.cloudmqtt.com"
#define mqtt_port 15443
#define mqtt_user "mqttuser"
#define mqtt_password "mqttpass"

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  // Set LED_BUILTIN 
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(115200);
  delay(10);

  Serial.println();

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

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
      return;
    }
  } else {
    // MQTT Topic /ESP32
    client.subscribe("/ESP32");
  }
  client.loop();
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  String msg = "";
  int i = 0;
  while (i < length) msg += (char)payload[i++];
  Serial.println(msg);
  digitalWrite(LED_BUILTIN, (msg == "on" ? LOW : HIGH));
}

Code แบบที่ 2 ใช้ WiFiManager ในการ config

#include                    //this needs to be first, or it all crashes and burns...
#include 
#include 
#include 
#include 

//flag for saving data
bool shouldSaveConfig = false;

//callback notifying us of the need to save config
void saveConfigCallback () {
  Serial.println("Should save config");
  shouldSaveConfig = true;
}

// Config MQTT Server
#define mqtt_server "m15.cloudmqtt.com"
#define mqtt_port 15443
#define mqtt_user "mqttuser"
#define mqtt_password "mqttpass"

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  // Set LED_BUILTIN 
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(115200);
  delay(10);

  Serial.println();

  WiFiManager wifiManager;
  wifiManager.autoConnect();

  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
}

void loop() {
  if (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
      return;
    }
  } else {
    // MQTT Topic /ESP32
    client.subscribe("/ESP32");
  }
  client.loop();
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  String msg = "";
  int i = 0;
  while (i < length) msg += (char)payload[i++];
  Serial.println(msg);
  digitalWrite(LED_BUILTIN, (msg == "on" ? LOW : HIGH));
}

Source Code ใน GitHub ตามนี้เลยครับ https://github.com/pornpasok/esp32_line_bot_mqtt

8.เรียบร้อยแล้ว ทดสอบใช้งาน

ทำการ Add LINE Bot ของเรา ก่อนนะ จากนั้นทดลองดังนี้ได้เลย

- ถ้าเราพิมพ์ On/on/เปิด/1 ไฟ LED ที่ตัว Node32 Lite ของเราก็จะติดครับ
- ถ้าเราพิมพ์ Off/off/ปิด/0 ไฟ LED ที่ตัว Node32 Lite ของเราก็จะดับครับ
- ถ้าเราพิมพ์ info/รายงาน บอทของเรา ก็จะรายงาน UID ของเราครับ เพื่อเอาไปใช้งานต่อยอดอื่นๆ

ปล. เดี๋ยวพรุ่งนี้ ถ่าย Video มาให้ดูกันนะครับ ว่าการทำงานของมันเป็นยังไง ถ่ายเองกดเอง ไม่ไหว 🙁

Next Step ...

- ต่อกับ Relay เพื่อใช้งานกับอุปกรณ์ไฟฟ้าจริงครับ (อันนี้อันตรายนะครับ ต้องระวังด้วยเพราะเล่นกับไฟ 220v)
- ต่อยอดให้ LINE Bot ของเรา มีความสามารถมากกว่านี้ครับ เช่น monitor หรือรายงาน ค่าต่างๆ ให้เราได้
- ทำ Box ให้ดี ให้สวยงาม กันน้ำ ติด Solar Cells เอาไปใช้งานจริงกันครับ ..

สำหรับท่านใด ที่มีข้อสงสัย หรือไม่เข้าใจตรงส่วนไหน สามารถ Post ถามได้ที่บทความนี้ครับ
หรือ Add LINE ID: pornpasok เข้ามาสอบถามก็ได้ครับ ถ้าตอบได้ผมจะตอบให้นะครับ 🙂

LINE Bot + node.js + MQTT + ESP32 (IoT) เปิด/ปิด ไฟ (ตอนที่ 1)

สวัสดีครับ เพื่อนๆ ทุกท่าน ผมเอง ไม่ได้ มา update blog เป็นเวลานานเหมือนกัน เผลอๆ แป๊บๆ ก็จะสิ้นปีอีกแล้ว ..

ปีนี้ ที่ผ่านมาผมได้มีโอกาสกลับไปอยู่บ้าน ที่จันทบุรี ได้ลงไปสัมผัส ไปเป็นเกษตรกรจริงๆ ด้วยตัวเอง ทำให้ได้รับประสบการณ์ ที่ดีมาก ได้รู้ว่าจริงๆ แล้ว เกษตรกร (ชาวสวน) เค้าต้องการอะไร เค้าขาดอะไร และทำอย่างไร จะทำให้ การทำงานมีประสิทธิภาพมากขึ้น มีเวลาพักผ่อนอยู่กับครอบครัวมากขึ้น มีความสุขมากขึ้น รายได้เพิ่มขึ้น และค่าใช้จ่ายลดลง ..

จึงเกิดเป็น Project นี้ขึ้นมา คือระบบเปิด/ปิด มอเตอร์สูบน้ำ ผ่าน LINE Bot หรือ LINE Messaging API นั่นเอง ที่ผมเลือกใช้ Chat Bot มาเป็นระบบสั่งเปิด/ปิด เพราะว่า เป็นการง่ายสำหรับเกษตรกร เพราะปกติเค้าใช้ LINE ผ่านมือถือกันอยู่แล้ว จะได้ไม่ต้องวุ่นวาย ลง App ใหม่ๆ หรือเรียนรู้ App ใหม่ๆ เพราะแค่พิมพ์ เปิด/ปิด มอเตอร์สูบน้ำ ที่อยู่ ที่สระน้ำสาธารณะ ของหมู่บ้าน หรือตามริมคลอง ริมแม่น้ำ ก็จะทำงานตามคำสั่งทันที ..

Stack ที่ผมใช้ ใน Project นี้ จะเป็น Open Source ทั้งหมด และมีให้เราใช้ฟรีๆ กันอยู่แล้ว ส่วนตัว H/W (IoT device)  ตอนแรก ผมสนใจ NB-IoT, LoRa เหมือนกัน เพราะตาม concept มันเหมาะมาก ในเรื่องของการรับส่งระยะไกล และประหยัดพลังงาน แต่ติดอยู่ที่ว่า ราคาของ H/W ยังสูง และเครือข่าย ยังไม่ครอบคลุมทั่วถึง ก็เลยกลับไปคิดถึง IoT device ที่เป็น WiFi 2.4GHz ทั่วๆ ไป ที่ราคาตอนนี้ ไม่แพง ประมาณ 100-150 บาท/บอร์ด เช่นพวกที่ใช้ chip ESP8266, ESP32 แทน และบริเวณที่ไปใช้งาน ไฟฟ้าเข้าถึงแล้ว จึงไม่ต้องห่วงเรื่องของพลังงานไฟฟ้า เท่าไรนัก แต่ถ้าเป็นไปได้ ก็จะทำให้อยู่ใน deep sleep mode เพราะจะทำให้ประหยัดพลังงานและ เกิดความร้อน น้อยกว่า mode ปกติ ..

Stack ต่างๆ สรุป มีดังต่อไปนี้ 
– LINE Messaging API (LINE Bot)
– node.js (Heroku)
– MQTT (Heroku)
– ESP32 (IoT device) + WiFiManager

อ่านต่อตอนที่ 2 (ตอนจบ) ได้ที่นี่ครับ http://ton.packetlove.com/blog/iot/line-bot-node-js-mqtt-esp32-iot-2.html

Add LINE มาลองเล่น กับ tonofarmbot กันดูได้ครับ