complete iot structure

This commit is contained in:
Siwat Sirichai 2023-12-28 14:52:52 +07:00
parent da277e1e4a
commit 0dfb066a74
10 changed files with 259 additions and 74 deletions

View File

@ -11,6 +11,7 @@ class AnalogIoT : public IoTComponent {
void setADCsPublishInterval(uint32_t interval);
void setADCsPublishEnabled(bool enabled);
void publishReport();
void subscribe();
uint8_t getType();
private:
char *adc_topic;

View File

@ -169,3 +169,25 @@ void DigitalOutputIoT::publishReport() {
uint8_t DigitalOutputIoT::getType() {
return CARD_TYPE_DIGITAL_OUTPUT;
}
void DigitalOutputIoT::subscribe() {
// Subscribe to all set state topics
for(int i = 1; i <= 16; i++) {
char topic[10];
sprintf(topic, "%02d/set/state", i);
subscribeRelative(topic);
}
// Subscribe to all set value topics
for(int i = 1; i <= 16; i++) {
char topic[10];
sprintf(topic, "%02d/set/value", i);
subscribeRelative(topic);
}
// Subscribe to request state topic
subscribeRelative(REQUEST_STATE_TOPIC);
// Subscribe to publish enable topic
subscribeRelative(PUBLISH_ENABLE_TOPIC);
}
void DigitalOutputIoT::loop() {
}

View File

@ -18,6 +18,8 @@ class DigitalOutputIoT : public IoTComponent {
void registerValueChangeCallback(void (*callback)(uint8_t, bool, uint16_t));
void deregisterValueChangeCallback();
void publishReport();
void subscribe();
void loop();
uint8_t getType();
private:
bool digital_outputs_publish_enabled = false;

View File

@ -1,5 +1,14 @@
#include <ESPMegaIoT.hpp>
ESPMegaIoT::ESPMegaIoT() {
// Initialize the components array
for (int i = 0; i < 255; i++) {
components[i] = NULL;
}
active = false;
mqtt_connected = false;
}
void ESPMegaIoT::mqttCallback(char *topic, byte *payload, unsigned int length) {
// Create a null terminated string from the payload
memcpy(payload_buffer, payload, length);
@ -17,6 +26,12 @@ void ESPMegaIoT::mqttCallback(char *topic, byte *payload, unsigned int length) {
return;
}
components[card_id]->handleMqttMessage(topic_without_base + 3, payload_buffer);
if (user_relative_mqtt_callback != NULL) {
user_relative_mqtt_callback(topic_without_base + 3, payload_buffer);
}
if (user_mqtt_callback != NULL) {
user_mqtt_callback(topic, payload_buffer);
}
}
void ESPMegaIoT::setBaseTopic(char *base_topic) {
@ -24,10 +39,23 @@ void ESPMegaIoT::setBaseTopic(char *base_topic) {
base_topic_length = strlen(base_topic);
}
void ESPMegaIoT::begin(ExpansionCard *cards[]) {
void ESPMegaIoT::intr_begin(ExpansionCard *cards[]) {
this->cards = cards;
ETH.begin();
active = true;
}
void ESPMegaIoT::loop() {
if(!active)
return;
// Call each component's loop function
for (int i = 0; i < 255; i++) {
if (components[i] != NULL) {
components[i]->loop();
}
}
mqtt.loop();
sessionKeepAlive();
}
void ESPMegaIoT::loop();
// Register Existing Card for use with IoT
void ESPMegaIoT::registerCard(uint8_t card_id) {
@ -54,11 +82,6 @@ void ESPMegaIoT::registerCard(uint8_t card_id) {
default:
return;
}
// Initialize the IoT component
// Enable publishing for the card
card_publish_enabled[card_id] = true;
}
void ESPMegaIoT::deregisterCard(uint8_t card_id) {
// Check if the card is registered
@ -68,8 +91,6 @@ void ESPMegaIoT::deregisterCard(uint8_t card_id) {
// Delete the IoT component
delete components[card_id];
components[card_id] = NULL;
// Disable publishing for the card
card_publish_enabled[card_id] = false;
}
void ESPMegaIoT::publishCard(uint8_t card_id) {
// Check if the card is registered
@ -103,13 +124,114 @@ void ESPMegaIoT::disconnectFromWifi() {
bool ESPMegaIoT::wifiConnected() {
return WiFi.status() == WL_CONNECTED;
}
void ESPMegaIoT::connectToMqtt(char*client_id, char *mqtt_server, uint16_t mqtt_port, char *mqtt_user, char *mqtt_password) {
bool ESPMegaIoT::connectToMqtt(char*client_id, char *mqtt_server, uint16_t mqtt_port, char *mqtt_user, char *mqtt_password) {
// Store mqtt connection parameters
this->mqtt_server = mqtt_server;
this->mqtt_port = mqtt_port;
this->mqtt_user = mqtt_user;
this->mqtt_password = mqtt_password;
this-> mqtt_useauth = true;
this->client_id = client_id;
mqtt.setServer(mqtt_server, mqtt_port);
mqtt.setCallback(mqttCallback);
mqtt.connect(client_id, mqtt_user, mqtt_password);
sessionKeepAlive();
auto boundCallback = std::bind(&ESPMegaIoT::mqttCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
mqtt.setCallback(boundCallback);
if (mqtt.connect(client_id, mqtt_user, mqtt_password)) {
sessionKeepAlive();
mqttSubscribe();
mqtt_connected = true;
return true;
}
mqtt_connected = false;
return false;
}
bool ESPMegaIoT::connectToMqtt(char* client_id, char *mqtt_server, uint16_t mqtt_port) {
// Store mqtt connection parameters
this->mqtt_server = mqtt_server;
this->mqtt_port = mqtt_port;
this->mqtt_useauth = false;
this->client_id = client_id;
mqtt.setServer(mqtt_server, mqtt_port);
auto boundCallback = std::bind(&ESPMegaIoT::mqttCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
mqtt.setCallback(boundCallback);
if(mqtt.connect(client_id)) {
sessionKeepAlive();
mqttSubscribe();
mqtt_connected = true;
return true;
}
mqtt_connected = false;
return false;
}
void ESPMegaIoT::disconnectFromMqtt() {
mqtt.disconnect();
}
void ESPMegaIoT::publishToTopic(char *topic, char *payload) {
mqtt.publish(topic, payload);
}
void ESPMegaIoT::registerMqttCallback(void (*callback)(char *, char *)) {
}
void ESPMegaIoT::mqttSubscribe() {
// Subscribe to all topics
for (int i = 0; i < 255; i++) {
if (components[i] != NULL) {
components[i]->subscribe();
}
}
}
void ESPMegaIoT::publishRelative(uint8_t card_id, char *topic, char *payload) {
char absolute_topic[100];
sprintf(absolute_topic, "%s/%d/%s", base_topic, card_id, topic);
mqtt.publish(absolute_topic, payload);
}
void ESPMegaIoT::setETHStaticIp(IPAddress ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) {
ETH.config(ip, gateway, subnet, dns1, dns2);
}
void ESPMegaIoT::setETHStaticIp(IPAddress ip, IPAddress gateway, IPAddress subnet, IPAddress dns1) {
ETH.config(ip, gateway, subnet, dns1);
}
void ESPMegaIoT::setETHStaticIp(IPAddress ip, IPAddress gateway, IPAddress subnet) {
ETH.config(ip, gateway, subnet);
}
IPAddress ESPMegaIoT::getETHIp() {
return ETH.localIP();
}
bool ESPMegaIoT::mqttReconnect() {
if (mqtt_useauth) {
return this->connectToMqtt(client_id, mqtt_server, mqtt_port, mqtt_user, mqtt_password);
} else {
return this->connectToMqtt(client_id, mqtt_server, mqtt_port);
}
}
void ESPMegaIoT::sessionKeepAlive() {
static unsigned long lastSessionKeepAlive = 0;
if (millis() - lastSessionKeepAlive > 30000) {
lastSessionKeepAlive = millis();
// Check if mqtt is connected
if (!mqtt.connected()) {
// Try to reconnect
mqtt_connected = mqttReconnect();
}
}
}
void ESPMegaIoT::registerRelativeMqttCallback(void (*callback)(char *, char *)) {
user_relative_mqtt_callback = callback;
}
void ESPMegaIoT::publishRelative(char *topic, char *payload) {
char absolute_topic[100];
sprintf(absolute_topic, "%s/%s", base_topic, topic);
mqtt.publish(absolute_topic, payload);
}
void ESPMegaIoT::subscribeRelative(char *topic) {
char absolute_topic[100];
sprintf(absolute_topic, "%s/%s", base_topic, topic);
mqtt.subscribe(absolute_topic);
}
void ESPMegaIoT::connectToMqtt(char* client_id, char *mqtt_server, uint16_t mqtt_port);
void ESPMegaIoT::disconnectFromMqtt();
void ESPMegaIoT::publishToTopic(char *topic, char *payload);
void ESPMegaIoT::registerMqttCallback(void (*callback)(char *, char *));

View File

@ -11,37 +11,58 @@
class ESPMegaIoT
{
public:
void begin(ExpansionCard *cards[]);
void loop();
void registerCard(uint8_t card_id);
void deregisterCard(uint8_t card_id);
void publishCard(uint8_t card_id);
void subscribeToTopic(char *topic);
void unsubscribeFromTopic(char *topic);
void connectToEthernet();
bool ethernetConnected();
void connectToWifi(char *ssid, char *password);
void connectToWifi(char *ssid);
void disconnectFromWifi();
bool wifiConnected();
void connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt_port, char *mqtt_user, char *mqtt_password);
void connectToMqtt(char* client_id, char *mqtt_server, uint16_t mqtt_port);
void disconnectFromMqtt();
void publishToTopic(char *topic, char *payload);
void registerMqttCallback(void (*callback)(char *, char *));
void setBaseTopic(char *base_topic);
private:
void sessionKeepAlive();
void mqttReconnect();
void wifiReconnect();
void mqttCallback(char *topic, byte *payload, unsigned int length);
void publishRelative(uint8_t card_id, char *topic, char *payload);
PubSubClient mqtt;
IoTComponent *components[255];
bool card_publish_enabled[255];
char payload_buffer[200];
char base_topic[100];
uint8_t base_topic_length;
ExpansionCard **cards; // Points to card array in ESPMegaPRO Core
public:
void intr_begin(ExpansionCard *cards[]);
void loop();
void registerCard(uint8_t card_id);
void deregisterCard(uint8_t card_id);
void publishCard(uint8_t card_id);
// Publish topic appended with base topic
void publishRelative(char *topic, char *payload);
// Subscribe topic appended with base topic
void subscribeRelative(char *topic);
void subscribeToTopic(char *topic);
void unsubscribeFromTopic(char *topic);
void connectToEthernet();
bool ethernetConnected();
void connectToWifi(char *ssid, char *password);
void connectToWifi(char *ssid);
void disconnectFromWifi();
bool wifiConnected();
bool connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt_port, char *mqtt_user, char *mqtt_password);
bool connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt_port);
void disconnectFromMqtt();
void publishToTopic(char *topic, char *payload);
void registerMqttCallback(void (*callback)(char *, char *));
void registerRelativeMqttCallback(void (*callback)(char *, char *));
void setBaseTopic(char *base_topic);
void setETHStaticIp(IPAddress ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2);
void setETHStaticIp(IPAddress ip, IPAddress gateway, IPAddress subnet, IPAddress dns1);
void setETHStaticIp(IPAddress ip, IPAddress gateway, IPAddress subnet);
IPAddress getETHIp();
private:
void sessionKeepAlive();
bool mqttReconnect();
void wifiReconnect();
void mqttSubscribe();
void mqttCallback(char *topic, byte *payload, unsigned int length);
void (*user_mqtt_callback)(char *, char *);
void (*user_relative_mqtt_callback)(char *, char *);
void publishRelative(uint8_t card_id, char *topic, char *payload);
bool active;
PubSubClient mqtt;
IoTComponent *components[255];
char payload_buffer[200];
char base_topic[100];
uint8_t base_topic_length;
ExpansionCard **cards; // Points to card array in ESPMegaPRO Core
// MQTT Connection Parameters
char *mqtt_server;
uint16_t mqtt_port;
char *mqtt_user;
char *mqtt_password;
char *client_id;
bool mqtt_useauth;
bool mqtt_connected;
};

View File

@ -28,6 +28,7 @@ void ESPMegaPRO::loop() {
cards[i]->loop();
}
}
iot.loop();
}
bool ESPMegaPRO::installCard(uint8_t slot, ExpansionCard* card) {
if (slot > 255) return false;
@ -88,3 +89,6 @@ void ESPMegaPRO::setTime(int hours, int minutes, int seconds, int day, int month
RTC.write(timeElement);
}
void ESPMegaPRO::enableIotModule() {
iot.intr_begin(cards);
}

View File

@ -32,6 +32,7 @@ class ESPMegaPRO {
void loop();
bool installCard(uint8_t slot, ExpansionCard* card);
bool updateTimeFromNTP();
void enableIotModule();
rtctime_t getTime();
void setTime(int hours, int minutes, int seconds, int day, int month, int year);
FRAM fram;

View File

@ -9,3 +9,13 @@ void IoTComponent::publishRelative(char *topic, char *payload) {
sprintf(absolute_topic, "%s/%d/%s", base_topic, card_id, topic);
mqtt->publish(absolute_topic, payload);
}
void IoTComponent::subscribeRelative(char *topic) {
char absolute_topic[100];
sprintf(absolute_topic, "%s/%d/%s", base_topic, card_id, topic);
mqtt->subscribe(absolute_topic);
}
void IoTComponent::loop() {
// Placeholder, Do nothing
}

View File

@ -8,9 +8,12 @@ class IoTComponent {
void setMqttClient(PubSubClient *mqtt);
virtual void publishReport();
virtual uint8_t getType();
virtual void subscribe();
void loop();
protected:
char *base_topic;
void publishRelative(char *topic, char *payload);
void subscribeRelative(char *topic);
PubSubClient *mqtt;
uint8_t card_id;
};

View File

@ -3,36 +3,35 @@
// Instantiate ESPMega
ESPMegaPRO espmega = ESPMegaPRO();
void mqtt_callback(char *topic, char *payload)
{
Serial.print("MQTT Callback: ");
Serial.print(topic);
Serial.print(" ");
Serial.println(payload);
}
void setup()
{
// Initialize ESPMega
espmega.begin();
Serial.println("ESPMega initialized");
espmega.enableIotModule();
espmega.iot.connectToEthernet();
IPAddress ip(192, 168, 0, 11);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
espmega.iot.setETHStaticIp(ip, gateway, subnet);
espmega.iot.setBaseTopic("/testmegaoop");
espmega.iot.connectToMqtt("espmega", "192.168.0.26", 1883);
espmega.iot.publishRelative("test", "test");
espmega.iot.subscribeRelative("test");
espmega.iot.registerMqttCallback(mqtt_callback);
Serial.println("ESPMega IoT initialized");
}
void loop()
{
// Read all the inputs and print them
for (int i = 0; i < 16; i++)
{
Serial.print("Input ");
Serial.print(i);
Serial.print(": ");
Serial.print(espmega.inputs.digitalRead(i));
Serial.println();
}
// Turn on all the outputs
for (int i = 0; i < 16; i++)
{
espmega.outputs.digitalWrite(i, true);
}
// Wait 1 second
delay(1000);
// Turn off all the outputs
for (int i = 0; i < 16; i++)
{
espmega.outputs.digitalWrite(i, false);
}
// Wait 1 second
delay(1000);
// Call ESPMega loop
espmega.loop();
}