#include <WiFi.h>
#include <PubSubClient.h>
#include <SPI.h>
#include <MFRC522.h>
#include <LiquidCrystal_I2C.h>
#include <freertos/task.h>
#include <time.h>
#define SS_PIN 5
#define RST_PIN 27
#define LED_PIN 2
MFRC522 mfrc522(SS_PIN, RST_PIN);
LiquidCrystal_I2C lcd(0x27, 16, 2);
// WiFi & ThingsBoard
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* tb_host = "demo.thingsboard.io";
const int tb_port = 1883;
const char* tb_token = "1fj3t0cg5es1mr1cnwab";
WiFiClient espClient;
PubSubClient client(espClient);
QueueHandle_t uidQueue;
int record_id = 0;
// Function: Format UID data as JSON
String formatTelemetryJson(String uid) {
time_t now;
struct tm timeinfo;
time(&now);
localtime_r(&now, &timeinfo);
char dateStr[11]; // yyyy-mm-dd
char timeStr[9]; // HH:MM:SS
strftime(dateStr, sizeof(dateStr), "%Y-%m-%d", &timeinfo);
strftime(timeStr, sizeof(timeStr), "%H:%M:%S", &timeinfo);
String json = "{";
json += "\"id\":" + String(++record_id) + ",";
json += "\"UID\":\"" + uid + "\",";
json += "\"date\":\"" + String(dateStr) + "\",";
json += "\"time\":\"" + String(timeStr) + "\"";
json += "}";
return json;
}
void reconnectMQTT() {
while (!client.connected()) {
Serial.println("Connecting to ThingsBoard...");
if (client.connect("ESP32_Client", tb_token, NULL)) {
Serial.println("Connected to ThingsBoard.");
} else {
Serial.print("Failed MQTT connection. rc=");
Serial.print(client.state());
Serial.println(" Retrying in 5 seconds...");
delay(5000);
}
}
}
// Core 0: 處理 WiFi + MQTT 傳送
void mqttTask(void *pvParameters) {
Serial.begin(115200);
SPI.begin();
mfrc522.PCD_Init();
pinMode(LED_PIN, OUTPUT);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("\nWiFi connected.");
Serial.println(WiFi.localIP());
configTime(8 * 3600, 0, "pool.ntp.org"); // 設定台灣時間
client.setServer(tb_host, tb_port);
String receivedUid;
while (true) {
if (!client.connected()) {
reconnectMQTT();
}
client.loop();
if (xQueueReceive(uidQueue, &receivedUid, portMAX_DELAY) == pdPASS) {
String payload = formatTelemetryJson(receivedUid);
Serial.println("Sending to ThingsBoard: " + payload);
if (client.publish("v1/devices/me/telemetry", payload.c_str())) {
digitalWrite(LED_PIN, HIGH);
vTaskDelay(500 / portTICK_PERIOD_MS);
digitalWrite(LED_PIN, LOW);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("RFID IOT");
lcd.setCursor(0, 1);
lcd.print(receivedUid);
} else {
Serial.println("Failed to publish to ThingsBoard.");
}
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
// Core 1: 模擬 RFID 掃描(按下 ENTER 觸發)
void rfidSimTask(void *pvParameters) {
Serial.println("Press ENTER to simulate RFID scan.");
while (true) {
if (Serial.available()) {
char c = Serial.read();
if (c == '\n' || c == '\r') {
while(Serial.available() && (Serial.peek() == '\n' || Serial.peek() == '\r')) {
Serial.read();
}
String uid = generateSpecificRangeUID();
Serial.print("Simulated UID: ");
Serial.println(uid);
if (xQueueSend(uidQueue, &uid, portMAX_DELAY) != pdPASS) {
Serial.println("Failed to send UID to queue.");
}
}
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
// 產生 UID 模擬資料
String generateSpecificRangeUID() {
unsigned long start_val = 0x8EED7100;
unsigned long end_val = 0x8EED71FF;
unsigned long random_val = random(start_val, end_val + 1);
char hex_uid[9];
sprintf(hex_uid, "%08lX", random_val);
return String(hex_uid);
}
void setup() {
lcd.init();
lcd.backlight();
Serial.begin(115200);
uidQueue = xQueueCreate(5, sizeof(String));
if (uidQueue == NULL) {
Serial.println("Queue creation failed. System halt.");
while (true);
}
xTaskCreatePinnedToCore(
mqttTask,
"MQTT_Task",
10000,
NULL,
1,
NULL,
0
);
xTaskCreatePinnedToCore(
rfidSimTask,
"RFID_Sim_Task",
4000,
NULL,
1,
NULL,
1
);
}
void loop() {
vTaskDelay(1);
}
沒有留言:
張貼留言