#include <WiFi.h>
#include <PubSubClient.h>
#include <time.h> // ไลบรารีสำหรับดึงเวลาจาก NTP
#include "esp_adc_cal.h"
extern "C" {
uint8_t temprature_sens_read();
}
// WiFi Credentials
const char *ssid = "xxx"; // เปลี่ยนเป็นชื่อ WiFi ของคุณ
const char *password = "xxx"; // เปลี่ยนเป็นรหัสผ่าน WiFi ของคุณ
// MQTT Broker Settings
const char *mqtt_server = "xxx"; // เปลี่ยนเป็น mqtt server ของคุณ
const int mqtt_port = 1883;
const char *mqtt_user = "";
const char *mqtt_pass = "";
// Sensor Settings
const int SENSOR_PIN = 4; // GPIO4 สำหรับเชื่อมต่อ flow sensor
volatile long pulse;
//Restart
unsigned long startMillis = 0; // เวลาเริ่มต้นสำหรับจับเวลา
const unsigned long rebootInterval = 300000; // 5 นาที = 300,000 ms ตั้งเวลารีบูต MCU
const char *DISPENSOR_ID = "xxx"; // ตั้งชื่อ ID ของอุปกรณ์ของคุณ
#define SEND_LED 25 // ขาที่ต่อ สำหรับ led แสดงการส่งข่้อมูล
#define WIFI_LED 13 // ขาที่ต่อ สำหรับ led แสดงการเชื่อมต่อ wifi
#define MQTT_LED 14 // ขาที่ต่อ สำหรับ led แสดงการเชื่อมต่อ mqtt
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (256)
char msg[MSG_BUFFER_SIZE];
// ตั้งค่า Timezone เป็น GMT+7 (ประเทศไทย)
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 7 * 3600; // UTC+7
const int daylightOffset_sec = 0;
void IRAM_ATTR increase() {
pulse++;
}
// ฟังก์ชันเชื่อมต่อ WiFi
void setup_wifi() {
Serial.print("Connecting to WiFi: ");
Serial.println(ssid);
digitalWrite(WIFI_LED, LOW);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
int attempt = 0;
while (WiFi.status() != WL_CONNECTED && attempt < 20) {
delay(1000);
Serial.print(".");
attempt++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi Connected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
Serial.print("MAC Address: ");
Serial.println(WiFi.macAddress());
Serial.print("WiFi Status: ");
Serial.println(WiFi.status());
digitalWrite(WIFI_LED, HIGH); // ติด LED ที่ IO1 เมื่อเชื่อม WiFi สำเร็จ
// ตั้งค่า NTP
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
delay(2000); //ก่อน MQTT 2 วิ
} else {
Serial.println("\nWiFi Connection Failed!");
digitalWrite(WIFI_LED, LOW); // ดับ LED ที่ IO1 เมื่อเชื่อม WiFi ไม่สำเร็จ
}
}
// ฟังก์ชัน Callback เมื่อได้รับ MQTT Message
void callback(char *topic, byte *payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
// เช็คค่าจาก Payload (0 หรือ 1) เพื่อควบคุม LED
if ((char)payload[0] == '1') {
digitalWrite(SEND_LED, LOW);
} else {
digitalWrite(SEND_LED, HIGH);
digitalWrite(MQTT_LED, LOW);//ดับ mqtt
}
}
// ฟังก์ชันเชื่อมต่อ MQTT
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
String clientId = String(DISPENSOR_ID) + "-" + String(random(0xffff), HEX);
if (client.connect(clientId.c_str(), mqtt_user, mqtt_pass)) {
Serial.println("Connected to MQTT Broker!");
digitalWrite(MQTT_LED, HIGH); // ติด LED ที่ IO3 เมื่อเชื่อมต่อ MQTT ได้
digitalWrite(WIFI_LED, LOW); // ดับ Wifi-LED
client.subscribe("KMITL/water");
} else {
int retryCount = 0;
while (!client.connected()) {
Serial.print("Failed, rc=");
Serial.print(client.state());
Serial.println(" Try again in 5 seconds...");
delay(2000);
retryCount++;
if (retryCount >= 5) {
Serial.println("Failed to connect 5 times. Restarting...");
digitalWrite(MQTT_LED, LOW);
ESP.restart();
}
}
}
}
}
// ฟังก์ชันดึงเวลาปัจจุบัน
String getTimeString() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
Serial.println("Failed to obtain time");
return "N/A";
}
char timeStr[20];
strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", &timeinfo);
return String(timeStr);
}
void setup() {
pinMode(SEND_LED, OUTPUT);
pinMode(WIFI_LED, OUTPUT);
pinMode(MQTT_LED, OUTPUT);
Serial.begin(115200);
pinMode(SENSOR_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(SENSOR_PIN), increase, RISING);
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
startMillis = millis();
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
unsigned long now = millis();
if (now - lastMsg > 20000) { // ส่งข้อมูลทุก 30 วินาที / หักไฟกระพริบ 10 วิ
lastMsg = now;
float volume = pulse * 1.25;
pulse = 0;
// รับเวลาปัจจุบัน
String timestamp = getTimeString();
Serial.print("Volume: ");
Serial.print(volume);
Serial.println(" ml");
uint8_t temp_farenheit = temprature_sens_read();
float temp_celsius = ( temp_farenheit - 32 ) / 1.8;
Serial.print("Internal Temperature (°C): ");
Serial.println(temp_celsius);
// ส่งข้อมูล MQTT พร้อม Timestamp
snprintf(msg, MSG_BUFFER_SIZE, "{\"id\":\"%s\",\"volume\":%.2f,\"timestamp\":\"%s\",\"ip\":\"%s\",\"Gateway ip\":\"%s\",\"MCU\":%.2f}",
DISPENSOR_ID, volume, timestamp.c_str(), WiFi.localIP().toString().c_str(), WiFi.gatewayIP().toString().c_str(), temp_celsius);
Serial.println(msg);
client.publish("KMITL/water", msg);
//ส่งข้อมูลไฟกระพริบ 50 ครั้ง 10 วินาที 10,000/50/2
for (int i = 0; i < 50; i++) {
digitalWrite(SEND_LED, LOW);
delay(100);
digitalWrite(SEND_LED, HIGH);
delay(100);
}
}
// ตรวจสอบว่าครบ 5 นาทีหรือยัง
if (millis() - startMillis >= rebootInterval) {
Serial.println("Rebooting MCU...");
delay(100); // หน่วงเล็กน้อยให้ข้อความส่งออกก่อน
ESP.restart(); // สั่งให้รีบูต
}
}
Leave a Reply