IoT Comment

This commit is contained in:
Siwat Sirichai 2024-01-01 11:14:33 +07:00
parent 9a0f02fcd9
commit d75d098247
2 changed files with 287 additions and 20 deletions

View file

@ -1,6 +1,11 @@
#include <ESPMegaIoT.hpp>
#include <ETH.h>
/**
* @brief Create a new ESPMegaIoT object
*
* @note You shold not create this object directly, Instead, you should use the ESPMegaPRO::iot object
*/
ESPMegaIoT::ESPMegaIoT() : mqtt(tcpClient)
{
tcpClient.setTimeout(TCP_TIMEOUT_SEC);
@ -13,10 +18,24 @@ ESPMegaIoT::ESPMegaIoT() : mqtt(tcpClient)
mqtt_connected = false;
}
/**
* @brief Destroy the ESPMegaIoT object
*/
ESPMegaIoT::~ESPMegaIoT()
{
}
/**
* @brief The mqtt callback function, This function is called when a message is received on a subscribed topic
*
* This function is called when a message is received on a subscribed topic
* The payload is copied to a buffer and a null terminator is added
* The payload is then passed to the respective card's mqtt callback
*
* @param topic The topic of the message
* @param payload The payload of the message in byte form
* @param length The length of the payload
*/
void ESPMegaIoT::mqttCallback(char *topic, byte *payload, unsigned int length)
{
// Create a null terminated string from the payload
@ -46,17 +65,33 @@ void ESPMegaIoT::mqttCallback(char *topic, byte *payload, unsigned int length)
components[card_id]->handleMqttMessage(topic_without_base + 3, payload_buffer);
}
/**
* @brief Set the base topic for the IoT
*
* @param base_topic The base topic
*/
void ESPMegaIoT::setBaseTopic(char *base_topic)
{
strcpy(this->mqtt_config.base_topic, base_topic);
base_topic_length = strlen(this->mqtt_config.base_topic);
}
/**
* @brief Begin the ESPMegaIoT object
*
* @param cards The array of ExpansionCard objects
*/
void ESPMegaIoT::intr_begin(ExpansionCard *cards[])
{
this->cards = cards;
active = true;
}
/**
* @brief The main loop for the ESPMegaIoT object
*
* @note Normally you should not call this function, Instead, you should call ESPMegaPRO::loop()
*/
void ESPMegaIoT::loop()
{
if (!active)
@ -73,7 +108,14 @@ void ESPMegaIoT::loop()
sessionKeepAlive();
}
// Register Existing Card for use with IoT
/**
* @brief Register an existing card for use with IoT
*
* This function registers an existing card for use with IoT
* The card should be installed using ESPMegaPRO::installCard() before calling this function
*
* @param card_id The id of the card
*/
void ESPMegaIoT::registerCard(uint8_t card_id)
{
// Check if the card is already registered
@ -127,6 +169,12 @@ void ESPMegaIoT::registerCard(uint8_t card_id)
return;
}
}
/**
* @brief Unregister a card
*
* @param card_id The id of the card
*/
void ESPMegaIoT::unregisterCard(uint8_t card_id)
{
// Check if the card is registered
@ -138,6 +186,10 @@ void ESPMegaIoT::unregisterCard(uint8_t card_id)
delete components[card_id];
components[card_id] = NULL;
}
/**
* @brief Publish all cards's reports
*/
void ESPMegaIoT::publishCard(uint8_t card_id)
{
// Check if the card is registered
@ -148,30 +200,76 @@ void ESPMegaIoT::publishCard(uint8_t card_id)
// Publish the card
components[card_id]->publishReport();
}
void ESPMegaIoT::subscribeToTopic(char *topic)
/**
* @brief Subscribe to a topic
*
* @param topic The topic to subscribe to
*/
void ESPMegaIoT::subscribe(char *topic)
{
mqtt.subscribe(topic);
}
/**
* @brief Unsubscribe from a topic
*
* @param topic The topic to unsubscribe from
*/
void ESPMegaIoT::unsubscribeFromTopic(char *topic)
{
mqtt.unsubscribe(topic);
}
/**
* @brief Connect to a wifi network
*
* @param ssid The SSID of the wifi network
* @param password The password of the wifi network
*/
void ESPMegaIoT::connectToWifi(char *ssid, char *password)
{
WiFi.begin(ssid, password);
}
/**
* @brief Connect to a unsecured wifi network
*
* @param ssid The SSID of the wifi network
*/
void ESPMegaIoT::connectToWifi(char *ssid)
{
WiFi.begin(ssid);
}
/**
* @brief Disconnect from the wifi network
*/
void ESPMegaIoT::disconnectFromWifi()
{
WiFi.disconnect();
}
/**
* @brief Check if the wifi is connected
*
* @return True if the wifi is connected, false otherwise
*/
bool ESPMegaIoT::wifiConnected()
{
return WiFi.status() == WL_CONNECTED;
}
/**
* @brief Connect to a MQTT broker with authentication
*
* @param client_id The client id to use
* @param mqtt_server The MQTT server to connect to
* @param mqtt_port The MQTT port to connect to
* @param mqtt_user The MQTT username to use
* @param mqtt_password The MQTT password to use
* @return True if the connection is successful, false otherwise
*/
bool ESPMegaIoT::connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt_port, char *mqtt_user, char *mqtt_password)
{
mqtt.setServer(mqtt_server, mqtt_port);
@ -201,6 +299,15 @@ bool ESPMegaIoT::connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt
mqtt_connected = false;
return false;
}
/**
* @brief Connect to a MQTT broker without authentication
*
* @param client_id The client id to use
* @param mqtt_server The MQTT server to connect to
* @param mqtt_port The MQTT port to connect to
* @return True if the connection is successful, false otherwise
*/
bool ESPMegaIoT::connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt_port)
{
ESP_LOGD("ESPMegaIoT", "Setting MQTT server to %s:%d", mqtt_server, mqtt_port);
@ -231,26 +338,51 @@ bool ESPMegaIoT::connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt
mqtt_connected = false;
return false;
}
/**
* @brief Disconnect from the MQTT broker
*/
void ESPMegaIoT::disconnectFromMqtt()
{
mqtt.disconnect();
}
/**
* @brief Publish a message to a topic
*
* @param topic The topic to publish to
* @param payload The payload to publish
*/
void ESPMegaIoT::publish(const char *topic, const char *payload)
{
mqtt.publish(topic, payload);
}
/**
* @brief Register a callback for MQTT messages
*
* @param callback The callback function
* @return The handler for the callback
*/
uint8_t ESPMegaIoT::registerMqttCallback(std::function<void(char *, char *)> callback)
{
mqtt_callbacks[mqtt_callbacks_handler_index] = callback;
return mqtt_callbacks_handler_index++;
}
/**
* @brief Unregister a callback
*
* @param handler The handler of the callback
*/
void ESPMegaIoT::unregisterMqttCallback(uint8_t handler)
{
mqtt_callbacks.erase(handler);
}
/**
* @brief Subscribe to all components's topics
*/
void ESPMegaIoT::mqttSubscribe()
{
ESP_LOGD("ESPMegaIoT", "Begin MQTT Subscription");
@ -271,6 +403,9 @@ void ESPMegaIoT::mqttSubscribe()
}
}
/**
* @brief Publish relative to the base topic
*/
void ESPMegaIoT::publishRelative(uint8_t card_id, char *topic, char *payload)
{
char absolute_topic[100];
@ -278,6 +413,9 @@ void ESPMegaIoT::publishRelative(uint8_t card_id, char *topic, char *payload)
mqtt.publish(absolute_topic, payload);
}
/**
* @brief Subscribe relative to the base topic
*/
bool ESPMegaIoT::mqttReconnect()
{
if (this->mqtt_config.mqtt_useauth)
@ -290,6 +428,10 @@ bool ESPMegaIoT::mqttReconnect()
}
}
/**
* @brief Keep the MQTT session alive
* @note This function is called automatically by the ESPMegaIoT object, You should not call this function directly
*/
void ESPMegaIoT::sessionKeepAlive()
{
// This reconnect the MQTT if it disconnect.
@ -316,17 +458,36 @@ void ESPMegaIoT::sessionKeepAlive()
}
}
/**
* @brief Register a callback for MQTT messages relative to the base topic
*
* The message's base topic will be removed before calling the callback
*
* @param callback The callback function
* @return The handler for the callback
*/
uint8_t ESPMegaIoT::registerRelativeMqttCallback(std::function<void(char *, char *)> callback)
{
mqtt_relative_callbacks[mqtt_relative_callbacks_handler_index] = callback;
return mqtt_relative_callbacks_handler_index++;
}
/**
* @brief Unregister a relative MQTT callback
*
* @param handler The handler of the callback
*/
void ESPMegaIoT::unregisterRelativeMqttCallback(uint8_t handler)
{
mqtt_relative_callbacks.erase(handler);
}
/**
* @brief Publish a message relative to the base topic
*
* @param topic The topic to publish to
* @param payload The payload to publish
*/
void ESPMegaIoT::publishRelative(char *topic, char *payload)
{
char absolute_topic[100];
@ -335,6 +496,11 @@ void ESPMegaIoT::publishRelative(char *topic, char *payload)
mqtt.loop();
}
/**
* @brief Subscribe to a topic relative to the base topic
*
* @param topic The topic to subscribe to
*/
void ESPMegaIoT::subscribeRelative(char *topic)
{
char absolute_topic[100];
@ -343,22 +509,41 @@ void ESPMegaIoT::subscribeRelative(char *topic)
mqtt.loop();
}
/**
* @brief Register a function to be called when the ESPMegaIoT object is subscribing to topics
*
* @param callback The callback function
* @return The handler for the callback
*/
uint8_t ESPMegaIoT::registerSubscribeCallback(std::function<void(void)> callback)
{
subscribe_callbacks[subscribe_callbacks_handler_index] = callback;
return subscribe_callbacks_handler_index++;
}
/**
* @brief Unregister a subscribe callback
*
* @param handler The handler of the callback
*/
void ESPMegaIoT::unregisterSubscribeCallback(uint8_t handler)
{
subscribe_callbacks.erase(handler);
}
/**
* @brief Set the network config
*
* @param network_config The network config struct
*/
void ESPMegaIoT::setNetworkConfig(NetworkConfig network_config)
{
this->network_config = network_config;
}
/**
* @brief Load the network config from FRAM
*/
void ESPMegaIoT::loadNetworkConfig()
{
// Load the network config from FRAM
@ -375,6 +560,9 @@ void ESPMegaIoT::loadNetworkConfig()
fram->read(IOT_FRAM_ADDRESS + 87, (uint8_t *)network_config.password, 32);
}
/**
* @brief Save the network config to FRAM
*/
void ESPMegaIoT::saveNetworkConfig()
{
// Save the network config to FRAM
@ -391,11 +579,17 @@ void ESPMegaIoT::saveNetworkConfig()
fram->write(IOT_FRAM_ADDRESS + 87, (uint8_t *)network_config.password, 32);
}
/**
* @brief Begin the ethernet interface
*/
void ESPMegaIoT::ethernetBegin()
{
ethernetIface->setHostname(network_config.hostname);
}
/**
* @brief Load the MQTT config from FRAM
*/
void ESPMegaIoT::loadMqttConfig()
{
// Load the mqtt config from FRAM
@ -409,6 +603,9 @@ void ESPMegaIoT::loadMqttConfig()
this->base_topic_length = strlen(mqtt_config.base_topic);
}
/**
* @brief Save the MQTT config to FRAM
*/
void ESPMegaIoT::saveMqttConfig()
{
fram->write16(IOT_FRAM_ADDRESS + 128, mqtt_config.mqtt_port);
@ -419,6 +616,9 @@ void ESPMegaIoT::saveMqttConfig()
fram->write(IOT_FRAM_ADDRESS + 227, (uint8_t *)mqtt_config.base_topic, 32);
}
/**
* @brief Connect to MQTT with the current config
*/
void ESPMegaIoT::connectToMqtt()
{
if (mqtt_config.mqtt_useauth)
@ -433,6 +633,9 @@ void ESPMegaIoT::connectToMqtt()
}
}
/**
* @brief Connect to the network using the current config
*/
void ESPMegaIoT::connectNetwork()
{
if (network_config.useWifi)
@ -454,38 +657,78 @@ void ESPMegaIoT::connectNetwork()
}
}
/**
* @brief Set the MQTT config
*
* @param mqtt_config The MQTT config struct
*/
void ESPMegaIoT::setMqttConfig(MqttConfig mqtt_config)
{
this->mqtt_config = mqtt_config;
this->base_topic_length = strlen(mqtt_config.base_topic);
}
/**
* @brief Bind an ethernet interface to the ESPMegaIoT object
*
* @param ethernetIface The ethernet interface to bind (ETH for ESPMegaPRO R3)
*/
void ESPMegaIoT::bindEthernetInterface(ETHClass *ethernetIface)
{
this->ethernetIface = ethernetIface;
}
/**
* @brief Get the IoTComponent object for a card
*
* @param card_id The id of the card
* @return The IoTComponent object for the card
*/
IoTComponent *ESPMegaIoT::getComponent(uint8_t card_id)
{
return components[card_id];
}
/**
* @brief Get the network config
*
* @warning You should not modify the returned struct directly
*
* @return The network config struct
*/
NetworkConfig *ESPMegaIoT::getNetworkConfig()
{
return &network_config;
}
/**
* @brief Get the MQTT config
*
* @warning You should not modify the returned struct directly
*
* @return The MQTT config struct
*/
MqttConfig *ESPMegaIoT::getMqttConfig()
{
return &mqtt_config;
}
/**
* @brief Check if the MQTT is connected
*
* @return True if the MQTT is connected, false otherwise
*/
bool ESPMegaIoT::mqttConnected()
{
//return mqtt_connected;
return mqtt.connected();
}
/**
* @brief Check if the network is connected
*
* @return True if the network is connected, false otherwise
*/
bool ESPMegaIoT::networkConnected()
{
if (network_config.useWifi)
@ -494,6 +737,12 @@ bool ESPMegaIoT::networkConnected()
return ethernetIface->linkUp();
}
/**
* @brief Bind a FRAM object to the ESPMegaIoT object
* @note This class is hardcode to use the FRAM address 34-300
*
* @param fram The FRAM object to bind
*/
void ESPMegaIoT::bindFRAM(FRAM *fram)
{
this->fram = fram;