#include <OPC.h>
#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
volatile byte outputData = 0;
volatile byte inputData = 0;
Adafruit_SSD1306 display(128, 64, &Wire, -1);
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "broker.emqx.io";
const int mqtt_port = 1883;
const char* mqtt_topic_input = "esp32/inputData";
const char* mqtt_topic_output = "esp32/outputData";
WiFiClient espClient;
PubSubClient client(espClient);
OPCSerial opc;
byte dataCallback(const char *itemID, const opcOperation opcOP, const byte value) {
if (opcOP == opc_opwrite) {
outputData = value;
char msg[4];
snprintf(msg, 4, "%d", outputData);
client.publish(mqtt_topic_output, msg);
updateOLED();
}
return inputData;
}
void setup_wifi() {
delay(10);
// Serial.println();
// Serial.print("Connecting to ");
// Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
// Serial.print(".");
}
// Serial.println("");
// Serial.println("WiFi connected");
// Serial.println("IP address: ");
// Serial.println(WiFi.localIP());
}
void mqtt_callback(char* topic, byte* payload, unsigned int length) {
// Serial.print("Message arrived [");
// Serial.print(topic);
// Serial.print("] ");
char message[length + 1];
strncpy(message, (char*)payload, length);
message[length] = '\0';
// Serial.println(message);
if (strcmp(topic, mqtt_topic_input) == 0) {
int value = atoi(message);
if (value >= 0 && value <= 255) {
inputData = value;
// Serial.print("Set inputData via MQTT: ");
// Serial.println(inputData);
updateOLED();
}
}
}
void reconnect_mqtt() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("ESP32OPCClient")) {
// Serial.println("connected");
client.subscribe(mqtt_topic_input);
} else {
// Serial.print("failed, rc=");
// Serial.print(client.state());
// Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void updateOLED() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("ESP32 OPC-MQTT Monitor");
display.drawLine(0, 12, 128, 12, SSD1306_WHITE);
display.setCursor(0, 20);
display.print("Input Data: ");
display.setTextSize(2);
display.println(inputData);
display.setTextSize(1);
display.setCursor(0, 45);
display.print("Output Data: ");
display.setTextSize(2);
display.println(outputData);
display.display();
}
void setupOLED() {
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.display();
delay(2000);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Initializing...");
display.display();
delay(1000);
}
void setup() {
Serial.begin(9600);
setupOLED();
display.clearDisplay();
display.setCursor(0, 0);
display.println("Connecting WiFi");
display.display();
setup_wifi();
display.clearDisplay();
display.setCursor(0, 0);
display.println("WiFi connected");
display.print("IP: ");
display.println(WiFi.localIP());
display.display();
delay(2000);
client.setServer(mqtt_server, mqtt_port);
client.setCallback(mqtt_callback);
opc.addItem(
"esp32.data",
opc_readwrite,
opc_byte,
dataCallback
);
display.clearDisplay();
display.setCursor(0, 0);
display.println("System ready");
display.print("MQTT: ");
display.println(mqtt_server);
display.display();
delay(2000);
updateOLED();
}
void loop() {
if (!client.connected()) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.println("MQTT disconnected");
display.print("Reconnecting...");
display.display();
reconnect_mqtt();
}
client.loop();
opc.processOPCCommands();
}