// =======================================================
// GH1-SensorNode (FINAL STABLE VERSION)
// MODE 1 : LAN -> MQTT TCP (ThingsBoard MQTT Transport)
// MODE 2 : WAN -> HTTPS REST (ThingsBoard)
// CONTROL : ATTRIBUTE CONTROL (BEST PRACTICE CE)
// =======================================================
#include <WiFi.h>
#include <PubSubClient.h>
#include <HTTPClient.h>
#include "DHT.h"
#include <Wire.h>
//#include <Adafruit_GFX.h>
//#include <Adafruit_SSD1306.h>
/* ================= MODE ================= */
#define MODE_IOT 2 // 1 = LAN, 2 = REMOTE
/* ================= WIFI ================= */
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""
//#define WIFI_SSID "TP-Link_9F02"
//#define WIFI_PASSWORD "35841319"
/* ================= THINGSBOARD ================= */
#define TB_TOKEN "4y8m3uojflk0fdliv9eo" //"4y8m3uojflk0fdliv9eo" // GH1-SensorNode
/* LAN (ThingsBoard MQTT Transport) */
#define TB_LAN_SERVER "192.168.1.101"
#define TB_LAN_PORT 1883
/* REMOTE */
#define TB_HOST "https://tb.andipensil.com"
/* ================= SENSOR ================= */
#define DHTPIN 4
#define DHTTYPE DHT22
#define LDR_PIN 34
/* ================= OUTPUT ================= */
#define LED_PIN 26
/* ================= OLED ================= */
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C
/* ================= OBJECT ================= */
WiFiClient espClient;
PubSubClient mqttClient(espClient);
HTTPClient http;
DHT dht(DHTPIN, DHTTYPE);
//Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
/* ================= STATE ================= */
bool ledState = false;
/* ================= WIFI ================= */
void setupWiFi() {
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected");
Serial.println(WiFi.localIP());
}
/* ================= MQTT ================= */
void reconnectMQTT() {
while (!mqttClient.connected()) {
Serial.print("Connecting MQTT...");
if (mqttClient.connect("GH1-SensorNode", TB_TOKEN, NULL)) {
Serial.println("CONNECTED");
// SUBSCRIBE ATTRIBUTE UPDATE (OPSI C)
mqttClient.subscribe("v1/devices/me/attributes");
} else {
Serial.print("FAILED, rc=");
Serial.println(mqttClient.state());
delay(3000);
}
}
}
/* ================= OLED ================= */
/*void drawOLED(float temp, float hum, float lux) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
#if MODE_IOT == 1
display.println("GH1-SensorNode-LAN");
#else
display.println("GH1-SensorNode-WAN");
#endif
display.drawLine(0, 10, 127, 10, SSD1306_WHITE);
display.setTextSize(2);
display.setCursor(0, 16);
display.print("T:");
display.print(temp, 1);
display.print("C");
display.setCursor(0, 34);
display.print("H:");
display.print(hum, 1);
display.print("%");
display.setTextSize(1);
display.setCursor(80, 54);
display.print("Lux:");
display.print((int)lux);
display.display();
}*/
/* ======================================================
ATTRIBUTE CALLBACK (ANTI RTO - BEST PRACTICE CE)
====================================================== */
void mqttCallback(char* topic, byte* payload, unsigned int length) {
payload[length] = '\0';
String msg = String((char*)payload);
// Contoh payload dari ThingsBoard:
// {"led":true}
// {"led":false}
if (msg.indexOf("\"led\":true") >= 0) {
ledState = true;
digitalWrite(LED_PIN, HIGH);
Serial.println("LED ON (Attribute)");
}
else if (msg.indexOf("\"led\":false") >= 0) {
ledState = false;
digitalWrite(LED_PIN, LOW);
Serial.println("LED OFF (Attribute)");
}
}
/* ================= SEND TELEMETRY ================= */
void sendTelemetry(float t, float h, float l) {
String payload = "{";
payload += "\"temperature\":" + String(t, 2) + ",";
payload += "\"humidity\":" + String(h, 2) + ",";
payload += "\"lux\":" + String(l, 2);
payload += "}";
#if MODE_IOT == 1
if (!mqttClient.connected()) reconnectMQTT();
mqttClient.publish("v1/devices/me/telemetry", payload.c_str());
#else
String url = String(TB_HOST) + "/api/v1/" + TB_TOKEN + "/telemetry";
http.begin(url);
http.addHeader("Content-Type", "application/json");
http.POST(payload);
http.end();
#endif
}
/* ================= SETUP ================= */
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
dht.begin();
Wire.begin(21, 22);
/*display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
display.clearDisplay();
display.println("Booting...");
display.display();*/
setupWiFi();
#if MODE_IOT == 1
mqttClient.setServer(TB_LAN_SERVER, TB_LAN_PORT);
mqttClient.setCallback(mqttCallback);
#endif
}
/* ================= LOOP ================= */
void loop() {
float t = dht.readTemperature();
float h = dht.readHumidity();
int adc = analogRead(LDR_PIN);
float lux = map(adc, 0, 4095, 1000, 0);
lux = constrain(lux, 0, 1000);
//drawOLED(t, h, lux);
sendTelemetry(t, h, lux);
if (MODE_IOT == 1) {
mqttClient.loop();
}
delay(2000);
}