#include <stdio.h>
#include <Wire.h>
#include <WiFi.h>
#include "DHTesp.h"
#include <ArduinoJson.h>
#include <string.h>
#include <stdlib.h>
#include <PubSubClient.h>
#include <vector>
struct Stm32Data{
const char* serialNumber;
const char* secretkey;
int connect;
};
Stm32Data stm32data = {
"stm32_1",
"phongdp112",
1
};
struct Actuator {
const char* actuatorSerialNumber;
int pin;
int autoNumber;
};
std::vector<Actuator> actuators = {
{"led1", 32,0},
{"led2", 25,0},
{"led3",26,0}
};
struct Sensor {
const char* sensorSerialNumber;
int pin;
int isActive;
};
std::vector<Sensor> sensors = {
{"temphumid", 15,0},
{"pir", 12,0}
};
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
String topic_connect_request;
String topic_connect_backend_response;
String topic_connect_frontend_response;
String topic_control_actuator_request;
String topic_control_sensor_request;
String topic_control_actuator_response_frontend;
String topic_control_actuator_response_backend;
String topic_control_sensor_response_frontend;
String topic_control_sensor_response_backend;
String topic_data_sensor_backend;
String topic_notify;
const char* wifi_name = "Wokwi-GUEST";
const char* wifi_password = "";
WiFiClient espClient;
PubSubClient client(espClient);
DHTesp dhtSensor;
void setup_wifi();
void setup_pin_mode();
void reconnect_mqtt();
void callback(const char* topic, byte* payload, unsigned int length) ;
void handleConnect(StaticJsonDocument<200>& docRequest);
void publishChar(const char* idRequest,char a);
void publishString (const char* topic, StaticJsonDocument<200>& json);
void handleActuator( StaticJsonDocument<200>& docRequest);
void handleSensor( StaticJsonDocument<200>& docRequest);
void handleDHT22Data();
void handlePir();
void setup(){
Serial.begin(9600);
setup_wifi();
setup_pin_mode();
dhtSensor.setup(15, DHTesp::DHT22);
topic_connect_request = "/stm32/connect/request/" + String(stm32data.serialNumber);
topic_connect_backend_response = "/stm32/connect/backend/response/" + String(stm32data.serialNumber);
topic_connect_frontend_response = "/stm32/connect/frontend/response/" + String(stm32data.serialNumber);
topic_control_actuator_request = "/stm32/control/actuator/frontend/request/"+String(stm32data.serialNumber);
topic_control_actuator_response_frontend = "/stm32/control/actuator/frontend/response/"+String(stm32data.serialNumber);
topic_control_actuator_response_backend = "/stm32/control/actuator/backend/response/"+String(stm32data.serialNumber);
topic_control_sensor_request = "/stm32/control/sensor/frontend/request/"+String(stm32data.serialNumber);
topic_control_sensor_response_frontend = "/stm32/control/sensor/frontend/response/"+String(stm32data.serialNumber);
topic_control_sensor_response_backend = "/stm32/control/sensor/backend/response/"+String(stm32data.serialNumber);
topic_data_sensor_backend = "/stm32/data/sensor/backend";
topic_notify = "/stm32/notify";
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
reconnect_mqtt();
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi lost, reconnecting...");
setup_wifi(); // Kết nối lại WiFi
}
if (!client.connected()) {
reconnect_mqtt(); // Kết nối lại MQTT nếu bị mất kết nối
}
handleDHT22();
handlePir();
client.loop();
delay(5000); // Đợi 2 giây trước khi đọc lại
}
void handleDHT22(){
TempAndHumidity data = dhtSensor.getTempAndHumidity();
float temp = data.temperature;
float humid = data.humidity;
int randomInRange1 = esp_random() % 10-5; // randomInRange sẽ nằm trong khoảng 0 đến 100
int randomInRange2 = esp_random()%10-5;
// Gửi dữ liệu qua cổng Serial
Serial.println("Temp: " + String(temp+randomInRange1) + "C");
Serial.println("Humidity: " + String(humid+randomInRange2) + "%");
StaticJsonDocument<200> docResponse;
docResponse["sensorSerialNumber"] = sensors[0].sensorSerialNumber;
JsonArray valueArray = docResponse.createNestedArray("value");
valueArray.add(temp+randomInRange1);
valueArray.add(humid+randomInRange2);
publishString(topic_data_sensor_backend.c_str(),docResponse);
}
void handlePir(){
int pir_value = digitalRead(sensors[1].pin);
if(pir_value==HIGH){
digitalWrite(actuators[1].pin, HIGH);
digitalWrite(actuators[2].pin,HIGH);
StaticJsonDocument<200> docResponse;
docResponse["notify"] = 1;
publishString(topic_notify.c_str(),docResponse);
}
else{
digitalWrite(actuators[1].pin, LOW);
digitalWrite(actuators[2].pin,LOW);
}
}
void setup_wifi(){
Serial.print("Connecting to WiFi");
WiFi.begin(wifi_name, wifi_password, 6);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println("WiFi Connected!");
}
void setup_pin_mode(){
for(int i=0;i<actuators.size();i++){
pinMode(actuators[i].pin, OUTPUT);
}
for(int i=0;i<sensors.size();i++){
pinMode(sensors[i].pin, INPUT);
}
}
void reconnect_mqtt(){
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
Serial.println("connected");
client.subscribe(topic_connect_request.c_str());
Serial.println("Subscribed to: "+topic_connect_request);
client.subscribe(topic_control_actuator_request.c_str());
Serial.print("Subscribed to: ");
Serial.println(topic_control_actuator_request);
client.subscribe(topic_control_sensor_request.c_str());
Serial.print("Subscribed to: ");
Serial.println(topic_control_sensor_request);
}else {
Serial.print(client.state());
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void callback(const char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
// Chuyển đổi payload thành chuỗi
String message = "";
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.println("Received message: " + message);
StaticJsonDocument<200> doc;
DeserializationError error = deserializeJson(doc, message);
if (error) {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
return;
}
String topicStr = String(topic);
if(topicStr.indexOf("/connect/")!=-1){
handleConnect(doc);
}
if(stm32data.connect==1){
if(topicStr.indexOf("/control/")!=-1&&topicStr.indexOf("/actuator/")!=-1){
handleActuator(doc);
}
if(topicStr.indexOf("/control/")!=-1&&topicStr.indexOf("/sensor/")!=-1){
handleSensor(doc);
}
}
}
void handleConnect(StaticJsonDocument<200>& docRequest){
const char* idRequest = docRequest["id"];
const char* code = docRequest["stm32SerialNumber"];
const char* sk = docRequest["secretKey"];
int connect = docRequest["connected"];
StaticJsonDocument<200> docResponse;
docResponse["idRequest"] = idRequest;
if(strcmp(code,stm32data.serialNumber)==0)
{
if(connect==1){
if(strcmp(sk,stm32data.secretkey)==0){
stm32data.connect = 1;
docResponse["connect"] = connect;
}
else{
docResponse["connect"] = -1;
}
}
else{
stm32data.connect = 0;
docResponse["connect"] = connect;
}
}
else{
docResponse["connect"] = -1;
}
publishString(topic_connect_backend_response.c_str(),docResponse);
}
void handleActuator(StaticJsonDocument<200>& docRequest){
const char* code = docRequest["deviceSerialNumber"];
const char* idRequest = docRequest["id"];
int turn = docRequest["turn"];
StaticJsonDocument<200> docResponse;
docResponse["idRequest"] = idRequest;
for(int i=0;i<actuators.size();i++){
if(strcmp(actuators[i].actuatorSerialNumber,code)==0){
if(turn==1){
digitalWrite(actuators[i].pin, HIGH);
docResponse["turn"]=1;
}
else{
digitalWrite(actuators[i].pin,LOW);
docResponse["turn"]=0;
}
publishString(topic_control_actuator_response_frontend.c_str(),docResponse);
break;
}
}
}
void handleSensor(StaticJsonDocument<200>& docRequest){
const char* code = docRequest["deivceSerialNumber"];
const char* idRequest = docRequest["id"];
int turn = docRequest["turn"];
StaticJsonDocument<200> docResponse;
docResponse["idRequest"] = idRequest;
for(int i=0;i<sensors.size();i++){
if(strcmp(sensors[i].sensorSerialNumber,code)==0){
if(turn==1){
Serial.println("Sensor " +String (code) + " OFF");
sensors[i].isActive = 1;
docResponse["turn"]=1;
}
else{
Serial.println("Sensor " + String(code) + " OFF");
sensors[i].isActive = 0;
docResponse["turn"]=0;
}
publishString(topic_control_sensor_response_frontend.c_str(),docResponse);
break;
}
}
}
void publishString (const char* topic, StaticJsonDocument<200>& json){
char buffer[200];
size_t n = serializeJson(json, buffer);
client.publish(topic, buffer, n);
Serial.println("Publish message: " +String(topic) + String(buffer));
}