/*
ESP32 HTTPClient Jokes API Example
https://wokwi.com/projects/342032431249883731
Copyright (C) 2022, Uri Shaked
*/
#include <WiFi.h>
#include <HTTPClient.h>
//#include <ArduinoJson.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Arduino.h>
#include <WiFi.h>
//#include <Wire.h>
#include <ArduinoJson.h>
#include "PubSubClient.h"
#define VERSION "0.2.5"
#define SDA_PIN 22
#define SCL_PIN 21
#define SEM_PERIOD 500
#define LED 2
#define WIFI_RESET 34
#define MQTT_SERVER "150.95.31.215"
#define MQTT_USER "test01"
#define MQTT_PASSWORD "pwd01"
String ssid = "Wokwi-GUEST";
String password = "";
TimerHandle_t tmr;
boolean flash = false;
SemaphoreHandle_t semI2C;
// MQTT
const uint64_t chipid = ESP.getEfuseMac();
const String device_id = String((uint16_t)(chipid >> 32), HEX) + String((uint32_t)chipid, HEX); //สร้างหมายเลข ID ของอุปกรณ์
const String notifyTopic = "device/" + device_id + "/notify";
const String gpioOnTopic = "gpio/" + String(device_id) + "/on";
const String gpioOnResultTopic = "gpio/" + String(device_id) + "/on/result";
const String gpioOffTopic = "gpio/" + String(device_id) + "/off";
const String gpioOffResultTopic = "gpio/" + String(device_id) + "/off/result";
const String gpioNotify = "gpio/" + String(device_id) + "/notify";
const String gpioReadTopic = "gpio/" + String(device_id) + "/read";
const String gpioReadResultTopic = "gpio/" + String(device_id) + "/read/result";
const String willTopic = "device/" + device_id + "/will";
int pins[] = {25, 26, 27, 32};
// MQTT Sub Pub Client
WiFiClient client;
PubSubClient mqttClient(client);
uint32_t lux;
void vTaskMqtt(void *pvParameters);
void vTaskSensor(void *pvParameters);
void ping(TimerHandle_t xTimer)
{
if (!flash)
{
digitalWrite(LED, !digitalRead(LED));
}
else
{
digitalWrite(LED, HIGH);
vTaskDelay(100 / portTICK_PERIOD_MS);
digitalWrite(LED, LOW);
}
}
void subscribe()
{
mqttClient.subscribe(gpioOnTopic.c_str());
mqttClient.subscribe(gpioOffTopic.c_str());
mqttClient.subscribe(gpioReadTopic.c_str());
}
void check_in()
{
String checkinTopic = "device/" + device_id + "/checkin";
DynamicJsonDocument doc(512);
JsonObject addr = doc.createNestedObject("addr");
addr["ip"] = WiFi.localIP().toString();
addr["subnet"] = WiFi.subnetMask().toString();
addr["gateway"] = WiFi.gatewayIP().toString();
addr["rssi"] = WiFi.RSSI();
doc["device_id"] = device_id;
doc["v"] = VERSION;
String jsonDoc = String();
serializeJson(doc, jsonDoc);
Serial.println(jsonDoc);
mqttClient.publish(checkinTopic.c_str(), jsonDoc.c_str());
}
void callback(char *topic, byte *payload, unsigned int length)
{
String _topic = String(topic);
String _payload = String((char *)payload).substring(0, length);
Serial.println(_topic);
DynamicJsonDocument doc(1024);
doc.clear();
if (_topic == gpioReadTopic)
{
if (xSemaphoreTake(semI2C, SEM_PERIOD) == pdTRUE)
{
doc["device_id"] = device_id;
JsonArray arry = doc.createNestedArray("gpios");
for (int n = 0; n < 4; n++)
{
JsonObject obj = arry.createNestedObject();
obj["index"] = n;
obj["state"] = digitalRead(pins[n]); // {25, 26, 27, 32};
}
xSemaphoreGive(semI2C);
}
String jsonDoc = String();
serializeJson(doc, jsonDoc);
Serial.println(jsonDoc);
Serial.println(gpioReadResultTopic);
mqttClient.publish(gpioReadResultTopic.c_str(), jsonDoc.c_str());
}
if (_topic == gpioOnTopic)
{
if (xSemaphoreTake(semI2C, SEM_PERIOD) == pdTRUE)
{
deserializeJson(doc, payload);
int index = doc["index"].as<int32_t>();
digitalWrite(pins[index], HIGH);
doc.clear();
doc["device_id"] = device_id;
doc["index"] = index;
doc["state"] = digitalRead(pins[index]);
xSemaphoreGive(semI2C);
}
String jsonDoc = String();
serializeJson(doc, jsonDoc);
Serial.println(jsonDoc);
mqttClient.publish(gpioOnResultTopic.c_str(), jsonDoc.c_str());
}
if (_topic == gpioOffTopic)
{
if (xSemaphoreTake(semI2C, SEM_PERIOD) == pdTRUE)
{
deserializeJson(doc, payload);
int index = doc["index"].as<int32_t>();
digitalWrite(pins[index], LOW);
doc.clear();
doc["device_id"] = device_id;
doc["index"] = index;
doc["state"] = digitalRead(pins[index]);
xSemaphoreGive(semI2C);
}
String jsonDoc = String();
serializeJson(doc, jsonDoc);
Serial.println(jsonDoc);
mqttClient.publish(gpioOffResultTopic.c_str(), jsonDoc.c_str());
}
}
void mqtt_init()
{
mqttClient.setServer(MQTT_SERVER, 1884);
mqttClient.setCallback(callback);
mqttClient.setKeepAlive(10);
String payload = "{\"device_id\": \"" + device_id + "\"}";
if (mqttClient.connect(device_id.c_str(), MQTT_USER, MQTT_PASSWORD, willTopic.c_str(), 0, false, payload.c_str()))
{
Serial.println("MQTT client connect success");
subscribe();
check_in();
xTaskCreatePinnedToCore(vTaskMqtt, "vTaskMqtt", 1024 * 4, NULL, tskIDLE_PRIORITY - 5, NULL, 1);
xTaskCreatePinnedToCore(vTaskSensor, "vTaskSensor", 1024 * 8, NULL, tskIDLE_PRIORITY - 5, NULL, 1);
}
else
{
Serial.println("MQTT client connect failed");
}
}
void vTaskMqtt(void *pvParameters)
{
while (true)
{
if (mqttClient.connected())
{
mqttClient.loop();
}
else
{
vTaskDelay(2000 / portTICK_PERIOD_MS);
if (mqttClient.connect(device_id.c_str(), MQTT_USER, MQTT_PASSWORD, willTopic.c_str(), 0, false, "{}"))
{
subscribe();
check_in();
Serial.println("MQTT client reconnect");
}
else
{
Serial.println("MQTT client reconnect failed");
}
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
void vTaskSensor(void *pvParameters)
{
vTaskDelay(1000 / portTICK_PERIOD_MS);
while (true)
{
// float humi = sht20.readHumidity(); // Read Humidity
// float temp = sht20.readTemperature(); // Read Temperature
/* sht.UpdateData();
float temp = sht.GetTemperature(); // Read Humidity
float humi = sht.GetRelHumidity(); // Read Temperature
uint32_t _lux = (uint32_t)lightMeter.readLightLevel();
if (_lux <= 65535)
{
lux = _lux;
} */
// random value for test
float humi = (float)(random(100, 999) / 10.0);
float temp = (float)(random(100, 999) / 10.0);
uint32_t lux = random(2000, 65535);
uint32_t soil = random(20, 100);
// Check if any reads failed and exit early (to try again).
DynamicJsonDocument doc(512);
doc["device_id"] = device_id;
doc["temperature"] = double((int(temp * 10)) / 10.0);
doc["humidity"] = double((int(humi * 10)) / 10.0);
doc["light"] = lux;
doc["soil"] = soil;
doc["rssi"] = WiFi.RSSI();
String jsonDoc = String();
serializeJson(doc, jsonDoc);
Serial.println(jsonDoc);
if (mqttClient.connected())
{
mqttClient.publish(notifyTopic.c_str(), jsonDoc.c_str());
}
vTaskDelay(15000 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
void WiFiStationConnected(WiFiEvent_t event, WiFiEventInfo_t info)
{
Serial.println("Connected to AP!");
Serial.print("SSID Length: ");
Serial.println(info.wifi_sta_connected.ssid_len);
Serial.print("SSID: ");
for (int i = 0; i < info.wifi_sta_connected.ssid_len; i++)
{
Serial.print((char)info.wifi_sta_connected.ssid[i]);
}
Serial.print("\nBSSID: ");
for (int i = 0; i < 6; i++)
{
Serial.printf("%02X", info.wifi_sta_connected.bssid[i]);
if (i < 5)
{
Serial.print(":");
}
}
Serial.print("\nChannel: ");
Serial.println(info.wifi_sta_connected.channel);
Serial.print("Auth mode: ");
Serial.println(info.wifi_sta_connected.authmode);
}
void WiFiStationGotIp(WiFiEvent_t event, WiFiEventInfo_t info)
{
Serial.println("WiFi got ip address");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
flash = true;
xTimerChangePeriod(tmr, 2000, 0);
mqtt_init();
}
void setup()
{
Serial.begin(115200);
pinMode(LED, OUTPUT);
pinMode(WIFI_RESET, INPUT_PULLUP);
delay(100);
semI2C = xSemaphoreCreateMutex();
tmr = xTimerCreate("MyTimer", 100, pdTRUE, NULL, &ping);
xTimerStart(tmr, 0);
Wire.setPins(SDA_PIN, SCL_PIN);
for (int i = 0; i < 4; i++)
{
pinMode(pins[i], OUTPUT);
}
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.onEvent(WiFiStationConnected, ARDUINO_EVENT_WIFI_STA_CONNECTED);
WiFi.onEvent(WiFiStationGotIp, ARDUINO_EVENT_WIFI_STA_GOT_IP);
WiFi.begin(ssid.c_str(), password.c_str());
Serial.print("DEVICE ID: "); //ปรินท์หมายเลข ID ของอุปกรณ์
Serial.println(device_id); //ชื่อหมายเลข ID
}
void loop()
{
/*
if (mqttClient.connected())
{
delay(500);
}
else
{
delay(500);
}
*/
}