🛑 อย่างที่สองคือ Line messaging API Line messaging API ที่จะใช้งานในโปรเจคอย่างกระทู้นี้ ทุกคนก็สามารถสมัครได้ฟรีโดยใช้งานได้ 300 ข้อความต่อเดือนซึ่งก็ถือว่าเหลือเฟือในการใช้งานเพื่อทดลองและเรียนรู้ครับ …. การใช้ Line messaging API จะต้องสมัคร LINE Official Account ก่อน … เริ่มที่นี่ครับ https://manager.line.biz/ ดูวิธีการสมัครที่นี่ (คลิปจากช่อง ครูอภิวัฒน์ “สอนสร้างสื่อ” https://www.youtube.com/@KruApiwat
เมื่อสมัคร LINE Official Account เสร็จแล้วก็ไป enable messaging API …. และเมื่อทุกอย่างเรียบร้อยแล้วทั้ง 4 ภาพด้านล่างนี้คือข้อมูล 2 ส่วนที่จะต้องใช้ไปใส่ใน ESP32 code ครับ
และในภาพนี้สังเกตจุดสีแดงกับน้ำเงินกระพริบอยู่ก็คือเป็นสาย jumper 2 เส้นที่ผมใช้แทน switch จำลองการเปิดประตูด้านหน้าและด้านหลังส่งข้อมูลไปยังเว็บ server เพื่อส่งข้อความเข้า LINE ในมือถือเมื่อประตูถูกเปิดหรือเมื่อความสว่างของแสงน้อยกว่าที่กำหนดครับ
คลิบนี้แสดงถึงการแจ้งเตือนผ่าน Line
Code ทั้งหมด
/*
ESP32-S3 N16R8 Data Logger & Monitor (Core 3.3.1)
Hardware Connections:
- DHT22 Data Pin: GPIO 5 (needs 10k pull-up resistor to 3.3V)
- LDR/Voltage Sensor: GPIO 1 (Analog input ADC1_CH0)
- Front Door Sensor: GPIO 7 (Logic input with internal pull-up)
- Back Door Sensor: GPIO 8 (Logic input with internal pull-up)
*/
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include <DHT.h>
// Wi-Fi Credentials
const char* ssid = "NT91124G";
const char* password = "911928TOT";
// API Endpoints & Credentials
const char* serverUrl = "https://www.navy007.com/temp32/data_receiver.php";
const char* lineApiUrl = "https://api.line.me/v2/bot/message/push";
const char* lineToken = " Line Token ของท่าน ";
const char* lineUserId = " User ID ของท่าน ";
// Pins
#define DHTPIN 5
#define DHTTYPE DHT22
#define VOLT_PIN 1
#define DOOR_FRONT_PIN 7
#define DOOR_BACK_PIN 8
DHT dht(DHTPIN, DHTTYPE);
// Timers (Non-blocking)
unsigned long lastDHTSend = 0;
unsigned long lastSensorRead = 0;
const unsigned long dhtInterval = 60000; // 1 minute
const unsigned long sensorInterval = 5000; // 5 seconds
// State tracking for LINE Spam Prevention
enum LightState { DARK, PARTLY_CLOUD, STRONG_SUN };
LightState currentLightState = STRONG_SUN;
bool isFirstLightRead = true;
int lastFrontDoorState = -1;
int lastBackDoorState = -1;
// Float definitions for tracking current values
float currentTemperature = 0.0;
float currentHumidity = 0.0;
float currentVoltGPIO1 = 0.0;
void setup() {
Serial.begin(115200);
// Setup Sensor Pins
dht.begin();
pinMode(VOLT_PIN, INPUT); // ADC1_CH0 (GPIO 1 is safe for ADC)
pinMode(DOOR_FRONT_PIN, INPUT_PULLUP);
pinMode(DOOR_BACK_PIN, INPUT_PULLUP);
// Setup Wi-Fi
WiFi.begin(ssid, password);
Serial.print("Connecting to Wi-Fi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to Wi-Fi Network!");
}
void loop() {
unsigned long currentMillis = millis();
// Task 1: Pull DHT22 Data every 1 minute
if (currentMillis - lastDHTSend >= dhtInterval) {
lastDHTSend = currentMillis;
readDHT22();
sendDataToServer();
}
// Task 2 & 3: Monitor GPIO 1, 7, and 8 every 5 seconds
if (currentMillis - lastSensorRead >= sensorInterval) {
lastSensorRead = currentMillis;
monitorPins();
}
}
void readDHT22() {
float temp = dht.readTemperature();
float hum = dht.readHumidity();
if (!isnan(temp) && !isnan(hum)) {
currentTemperature = temp;
currentHumidity = hum;
Serial.printf("DHT22 - Temp: %.2f C, Hum: %.2f%%\n", temp, hum);
} else {
Serial.println("Error reading from DHT22");
}
}
void monitorPins() {
// --- GPIO 1 Voltage Monitoring ---
// ESP32-S3 ADC has 12-bit resolution (0-4095) spanning ~3.1V depending on calibration
int rawADC = analogRead(VOLT_PIN);
currentVoltGPIO1 = (rawADC / 4095.0) * 3.3; // Estimated voltage scale
LightState computedState;
if (currentVoltGPIO1 < 2.0) {
computedState = DARK;
} else if (currentVoltGPIO1 >= 2.0 && currentVoltGPIO1 <= 2.35) {
computedState = PARTLY_CLOUD;
} else {
computedState = STRONG_SUN;
}
// Handle state change for light sensor to prevent spamming
if (computedState != currentLightState || isFirstLightRead) {
currentLightState = computedState;
isFirstLightRead = false;
if (currentLightState == DARK) {
sendLineMessage("ระดับแสงต่ำเกินไป");
}
}
// --- GPIO 7 (Front Door) & GPIO 8 (Back Door) Monitoring ---
int frontDoor = digitalRead(DOOR_FRONT_PIN);
int backDoor = digitalRead(DOOR_BACK_PIN);
// Spam prevention check for front door
if (frontDoor != lastFrontDoorState) {
lastFrontDoorState = frontDoor;
if (frontDoor == HIGH) { // Logic 1 = Open
sendLineMessage("ประตูหน้าเปิด");
}
}
// Spam prevention check for back door
if (backDoor != lastBackDoorState) {
lastBackDoorState = backDoor;
if (backDoor == HIGH) { // Logic 1 = Open
sendLineMessage("ประตูหลังเปิด");
}
}
Serial.printf("GPIO1: %.2f V, Front: %d, Back: %d\n", currentVoltGPIO1, frontDoor, backDoor);
}
// Function to Send Official LINE Push Notification
void sendLineMessage(String message) {
if (WiFi.status() != WL_CONNECTED) return;
WiFiClientSecure client;
client.setInsecure(); // Required for share hosting or API calls where cert pinning isn't hardcoded
HTTPClient http;
http.begin(client, lineApiUrl);
http.addHeader("Content-Type", "application/json");
http.addHeader("Authorization", "Bearer " + String(lineToken));
// Construct official LINE Push Message JSON
String jsonPayload = "{\"to\":\"" + String(lineUserId) + "\",\"messages\":[{\"type\":\"text\",\"text\":\"" + message + "\"}]}";
int httpResponseCode = http.POST(jsonPayload);
if (httpResponseCode > 0) {
Serial.println("LINE Push Sent successfully: " + String(httpResponseCode));
} else {
Serial.println(String("Error sending LINE Push: ") + http.errorToString(httpResponseCode).c_str());
}
http.end();
}
// Push latest telemetry to the Apache Share Hosting Server
void sendDataToServer() {
if (WiFi.status() != WL_CONNECTED) return;
WiFiClientSecure client;
client.setInsecure();
HTTPClient http;
http.begin(client, serverUrl);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
// Format POST payload
String postData = "temp=" + String(currentTemperature, 2) +
"&volt=" + String(currentVoltGPIO1, 2) +
"&front_door=" + String(lastFrontDoorState) +
"&back_door=" + String(lastBackDoorState);
int httpResponseCode = http.POST(postData);
if (httpResponseCode > 0) {
Serial.println("Telemetry synced: " + String(httpResponseCode));
} else {
Serial.println(String("Error syncing telemetry: ") + http.errorToString(httpResponseCode).c_str());
}
http.end();
}
จากภาพบน ค่าความต้านทาน LDR เปลี่ยนแปลงไม่เป็นเชิงเส้นกับความสว่างของแสง (A ในภาพ) ดังนั้นจากการเปลี่ยนแปลงที่ไม่เป็นเชิงเส้นทำให้คำนวณง่าย ๆ ไม่ได้ เราจะต้องทำดังนี้ …. 🛑 ดึง raw data ความต้านทาน vs ความสว่างออกมาจากกราฟใน datasheet (B ในภาพ) ซึ่งงานแบบนี้ AI ถนัดมาก เพียงแค่โยนภาพกราฟนี้เข้า AI ก็จะได้ตัวเลข raw data ของภาพทั้งหมด 🛑 ความสัมพันธ์ที่ไม่เป็นเชิงเส้นระหว่างค่าความต้านทานกับค่าความสว่างจะต้องใช้ Power law เพื่อหาสมการระหว่างค่าความต้านทานกับค่าความสว่าง (Lux) …. รายละเอียดการคำนวณตามภาพล่าง