completed InputCard
This commit is contained in:
parent
9f6512bf71
commit
75aa6f490b
|
@ -1,11 +1,12 @@
|
|||
#include <DigitalInputIoT.hpp>
|
||||
|
||||
|
||||
bool DigitalInputIoT::begin(uint8_t card_id, DigitalInputCard *card, PubSubClient *mqtt, char *base_topic) {
|
||||
this->card = card;
|
||||
bool DigitalInputIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic) {
|
||||
this->card = (DigitalInputCard *)card;
|
||||
this->card_id = card_id;
|
||||
this->mqtt = mqtt;
|
||||
this->base_topic = base_topic;
|
||||
this->setDigitalInputsPublishEnabled(true);
|
||||
this->card->registerCallback(std::bind(&DigitalInputIoT::handleValueChange, this, std::placeholders::_1, std::placeholders::_2));
|
||||
return true;
|
||||
|
||||
|
@ -63,9 +64,12 @@ uint8_t DigitalInputIoT::getType() {
|
|||
|
||||
|
||||
void DigitalInputIoT::publishDigitalInput(uint8_t pin) {
|
||||
char topic[64];
|
||||
char payload[2];
|
||||
sprintf(topic, "%s/%d/%d", this->base_topic, this->card_id, pin);
|
||||
sprintf(payload, "%d", this->card->digitalRead(pin, false));
|
||||
char topic[20] = {0};
|
||||
char payload[20] = {0};
|
||||
topic[0] = pin-pin%10 + '0';
|
||||
topic[1] = pin%10 + '0';
|
||||
topic[2] = '\0';
|
||||
payload[0] = this->card->digitalRead(pin, false) + '0';
|
||||
payload[1] = '\0';
|
||||
this->publishRelative(topic, payload);
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
class DigitalInputIoT : public IoTComponent {
|
||||
public:
|
||||
bool begin(uint8_t card_id, DigitalInputCard *card, PubSubClient *mqtt, char *base_topic);
|
||||
bool begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic);
|
||||
void handleMqttMessage(char *topic, char *payload);
|
||||
void publishDigitalInputs();
|
||||
void publishDigitalInput(uint8_t pin);
|
||||
|
@ -19,9 +19,6 @@ class DigitalInputIoT : public IoTComponent {
|
|||
void subscribe();
|
||||
uint8_t getType();
|
||||
private:
|
||||
uint8_t card_id;
|
||||
PubSubClient *mqtt;
|
||||
char *base_topic;
|
||||
std::function<void(uint8_t, uint8_t)> change_callback;
|
||||
bool digital_inputs_publish_enabled = false;
|
||||
DigitalInputCard *card;
|
||||
|
|
|
@ -12,8 +12,6 @@ DigitalOutputIoT::~DigitalOutputIoT() {
|
|||
}
|
||||
|
||||
bool DigitalOutputIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic) {
|
||||
Serial.print("Initializing digital output IoT component for card ");
|
||||
Serial.println(card_id);
|
||||
this->mqtt = mqtt;
|
||||
this->base_topic = base_topic;
|
||||
this->card = (DigitalOutputCard *) card;
|
||||
|
@ -42,15 +40,10 @@ bool DigitalOutputIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient
|
|||
// Publish all topic: requeststate payload: N/A
|
||||
// Enable/disable publish topic: publish_enable payload: 0/1
|
||||
void DigitalOutputIoT::handleMqttMessage(char *topic, char *payload) {
|
||||
Serial.print("Handling mqtt message for digital output IoT component for card ");
|
||||
Serial.println(card_id);
|
||||
Serial.print("Topic: ");
|
||||
Serial.println(topic);
|
||||
uint8_t topic_length = strlen(topic);
|
||||
if(this-> processSetStateMessage(topic, payload, topic_length)) return;
|
||||
if(this-> processSetValueMessage(topic, payload, topic_length)) return;
|
||||
if(this-> processRequestStateMessage(topic, payload, topic_length)) return;
|
||||
Serial.println("No handler found");
|
||||
}
|
||||
|
||||
bool DigitalOutputIoT::processSetStateMessage(char *topic, char *payload, uint8_t topic_length) {
|
||||
|
@ -61,22 +54,16 @@ bool DigitalOutputIoT::processSetStateMessage(char *topic, char *payload, uint8_
|
|||
if(topic[2] != '/') {
|
||||
return false;
|
||||
}
|
||||
Serial.println("Set state first check passed");
|
||||
// The topic must be set_state_length + 2 characters long
|
||||
if(topic_length != set_state_length + 2) {
|
||||
return false;
|
||||
}
|
||||
Serial.println("Set state second check passed");
|
||||
// Check if the topic ends with /set/state
|
||||
if (!strncmp(topic+2, SET_STATE_TOPIC, set_state_length)) {
|
||||
Serial.println("Set state third check passed");
|
||||
// Get the pin number
|
||||
uint8_t pin = (topic[0] - '0')*10 + (topic[1] - '0');
|
||||
Serial.print("Pin: ");
|
||||
Serial.println(pin);
|
||||
// Get the state
|
||||
bool state = false;
|
||||
Serial.println(payload);
|
||||
char state_char = payload[0];
|
||||
if (state_char == '0') {
|
||||
state = false;
|
||||
|
@ -85,8 +72,6 @@ bool DigitalOutputIoT::processSetStateMessage(char *topic, char *payload, uint8_
|
|||
} else {
|
||||
return false;
|
||||
}
|
||||
Serial.print("State: ");
|
||||
Serial.println(state);
|
||||
// Set the state
|
||||
card->setState(pin, state);
|
||||
return true;
|
||||
|
@ -99,19 +84,15 @@ bool DigitalOutputIoT::processSetValueMessage(char *topic, char *payload, uint8_
|
|||
// The correct format is <pin>/set/value
|
||||
// This mean that the topic must end with /set/value
|
||||
// Check if the 3rd character is /
|
||||
Serial.println("Set value first check");
|
||||
if(topic[2] != '/') {
|
||||
return false;
|
||||
}
|
||||
Serial.println("Set value first check passed");
|
||||
// The topic must be set_value_length + 2 characters long
|
||||
if(topic_length != set_value_length + 2) {
|
||||
return false;
|
||||
}
|
||||
Serial.println("Set value second check passed");
|
||||
// Check if the topic ends with /set/value
|
||||
if (!strncmp(topic+2, SET_VALUE_TOPIC, set_value_length)) {
|
||||
Serial.println("Set value third check passed");
|
||||
// Get the pin number
|
||||
uint8_t pin = (topic[0] - '0')*10 + (topic[1] - '0');
|
||||
// Get the value
|
||||
|
@ -128,18 +109,11 @@ bool DigitalOutputIoT::processRequestStateMessage(char *topic, char *payload, ui
|
|||
// The correct format is requeststate
|
||||
// This mean that the topic must be request_state_length characters long
|
||||
// The topic must be request_state_length characters long
|
||||
Serial.println("Request state first check");
|
||||
Serial.print("Topic length: ");
|
||||
Serial.println(topic_length);
|
||||
Serial.print("Request state length: ");
|
||||
Serial.println(request_state_length);
|
||||
if(topic_length != request_state_length) {
|
||||
return false;
|
||||
}
|
||||
Serial.println("Request state first check passed");
|
||||
// Check if the topic is requeststate
|
||||
if (!strncmp(topic, REQUEST_STATE_TOPIC, request_state_length)) {
|
||||
Serial.println("Request state second check passed");
|
||||
// Publish the state of all pins
|
||||
publishDigitalOutputs();
|
||||
return true;
|
||||
|
@ -149,7 +123,6 @@ bool DigitalOutputIoT::processRequestStateMessage(char *topic, char *payload, ui
|
|||
|
||||
void DigitalOutputIoT::publishDigitalOutputs() {
|
||||
if(!digital_outputs_publish_enabled) return;
|
||||
Serial.println("Publishing digital outputs");
|
||||
for(int i = 0; i < 16; i++) {
|
||||
publishDigitalOutput(i);
|
||||
}
|
||||
|
@ -204,27 +177,21 @@ uint8_t DigitalOutputIoT::getType() {
|
|||
}
|
||||
|
||||
void DigitalOutputIoT::subscribe() {
|
||||
Serial.println("Subscribing to digital output topics");
|
||||
char topic[20];
|
||||
Serial.println("Subscribe to all set state topics");
|
||||
// Subscribe to all set state topics
|
||||
for(int i = 0; i < 16; i++) {
|
||||
sprintf(topic, "%02d/set/state", i);
|
||||
subscribeRelative(topic);
|
||||
}
|
||||
Serial.println("Subscribe to all set value topics");
|
||||
// Subscribe to all set value topics
|
||||
for(int i = 0; i < 16; i++) {
|
||||
sprintf(topic, "%02d/set/value", i);
|
||||
subscribeRelative(topic);
|
||||
}
|
||||
Serial.println("Subscribe to request state topic");
|
||||
// Subscribe to request state topic
|
||||
subscribeRelative(REQUEST_STATE_TOPIC);
|
||||
Serial.println("Subscribe to publish enable topic");
|
||||
// Subscribe to publish enable topic
|
||||
subscribeRelative(PUBLISH_ENABLE_TOPIC);
|
||||
Serial.println("Subscriptions complete");
|
||||
}
|
||||
|
||||
void DigitalOutputIoT::loop() {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <ESPMegaIoT.hpp>
|
||||
|
||||
#include <ETH.h>
|
||||
#define NETWORK_CONFIG_ADDRESS 34
|
||||
#define MQTT_CONFIG_ADDRESS 34 + sizeof(NetworkConfig)
|
||||
|
||||
|
@ -15,6 +15,12 @@ ESPMegaIoT::ESPMegaIoT() : mqtt(tcpClient)
|
|||
mqtt_connected = false;
|
||||
}
|
||||
|
||||
ESPMegaIoT::~ESPMegaIoT()
|
||||
{
|
||||
// Delete the mqtt server
|
||||
delete[] mqtt_server;
|
||||
}
|
||||
|
||||
void ESPMegaIoT::mqttCallback(char *topic, byte *payload, unsigned int length)
|
||||
{
|
||||
// Create a null terminated string from the payload
|
||||
|
@ -34,11 +40,7 @@ void ESPMegaIoT::mqttCallback(char *topic, byte *payload, unsigned int length)
|
|||
// Note that after the base topic, there should be the card id
|
||||
// /base_topic/card_id/...
|
||||
// First, get the card id in integer form
|
||||
Serial.print("Topic: ");
|
||||
Serial.println(topic_without_base);
|
||||
char *card_id_str = strtok(topic_without_base, "/");
|
||||
Serial.print("Card ID: ");
|
||||
Serial.println(card_id_str);
|
||||
uint8_t card_id = atoi(card_id_str);
|
||||
// Check if the card is registered
|
||||
if (components[card_id] == NULL)
|
||||
|
@ -95,6 +97,11 @@ void ESPMegaIoT::registerCard(uint8_t card_id)
|
|||
case CARD_TYPE_DIGITAL_INPUT:
|
||||
components[card_id] = new DigitalInputIoT();
|
||||
components[card_id]->begin(card_id, cards[card_id], &mqtt, base_topic);
|
||||
if (mqtt_connected)
|
||||
{
|
||||
components[card_id]->subscribe();
|
||||
components[card_id]->publishReport();
|
||||
}
|
||||
break;
|
||||
case CARD_TYPE_DIGITAL_OUTPUT:
|
||||
components[card_id] = new DigitalOutputIoT();
|
||||
|
@ -106,10 +113,9 @@ void ESPMegaIoT::registerCard(uint8_t card_id)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
Serial.println("Invalid card type");
|
||||
Serial.println("Unsupported card type");
|
||||
return;
|
||||
}
|
||||
Serial.println("Card registered");
|
||||
}
|
||||
void ESPMegaIoT::deregisterCard(uint8_t card_id)
|
||||
{
|
||||
|
@ -158,13 +164,6 @@ bool ESPMegaIoT::wifiConnected()
|
|||
}
|
||||
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);
|
||||
auto boundCallback = std::bind(&ESPMegaIoT::mqttCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||
mqtt.setCallback(boundCallback);
|
||||
|
@ -188,26 +187,13 @@ bool ESPMegaIoT::connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt
|
|||
}
|
||||
bool ESPMegaIoT::connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt_port)
|
||||
{
|
||||
// Store mqtt connection parameters
|
||||
Serial.println("Storing mqtt connection parameters");
|
||||
this->mqtt_server = mqtt_server;
|
||||
this->mqtt_port = mqtt_port;
|
||||
this->mqtt_useauth = false;
|
||||
this->client_id = client_id;
|
||||
Serial.println("Setting mqtt server");
|
||||
mqtt.setServer(mqtt_server, mqtt_port);
|
||||
Serial.println("Setting mqtt callback");
|
||||
auto boundCallback = std::bind(&ESPMegaIoT::mqttCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||
mqtt.setCallback(boundCallback);
|
||||
Serial.println("Connecting to mqtt");
|
||||
if (mqtt.connect(client_id))
|
||||
{
|
||||
Serial.println("Connected to mqtt");
|
||||
Serial.println("Calling session keep alive");
|
||||
sessionKeepAlive();
|
||||
Serial.println("Subscribing to topics");
|
||||
mqttSubscribe();
|
||||
Serial.println("Publishing all cards");
|
||||
// Publish all cards
|
||||
for (int i = 0; i < 255; i++)
|
||||
{
|
||||
|
@ -237,7 +223,6 @@ void ESPMegaIoT::registerMqttCallback(void (*callback)(char *, char *))
|
|||
}
|
||||
void ESPMegaIoT::mqttSubscribe()
|
||||
{
|
||||
Serial.println("MQTT Subscribe Activated");
|
||||
if (user_subscribe_callback != NULL)
|
||||
{
|
||||
user_subscribe_callback();
|
||||
|
@ -313,7 +298,7 @@ void ESPMegaIoT::registerSubscribeCallback(void (*callback)(void))
|
|||
void ESPMegaIoT::setNetworkConfig(NetworkConfig network_config)
|
||||
{
|
||||
this->network_config = network_config;
|
||||
this->connectNetwork();
|
||||
client_id = network_config.hostname;
|
||||
}
|
||||
|
||||
void ESPMegaIoT::loadNetworkConfig()
|
||||
|
@ -330,8 +315,7 @@ void ESPMegaIoT::saveNetworkConfig()
|
|||
|
||||
void ESPMegaIoT::ethernetBegin()
|
||||
{
|
||||
ETH.begin();
|
||||
ETH.setHostname(network_config.hostname);
|
||||
ethernetIface->setHostname(network_config.hostname);
|
||||
}
|
||||
|
||||
void ESPMegaIoT::loadMqttConfig()
|
||||
|
@ -388,15 +372,38 @@ void ESPMegaIoT::connectNetwork()
|
|||
{
|
||||
this->ethernetBegin();
|
||||
if (network_config.useStaticIp)
|
||||
ETH.config(network_config.ip, network_config.gateway, network_config.subnet, network_config.dns1, network_config.dns2);
|
||||
ethernetIface->config(network_config.ip, network_config.gateway, network_config.subnet, network_config.dns1, network_config.dns2);
|
||||
}
|
||||
}
|
||||
|
||||
void ESPMegaIoT::setMqttConfig(MqttConfig mqtt_config)
|
||||
{
|
||||
if (mqtt_server != nullptr) {
|
||||
delete[] mqtt_server;
|
||||
}
|
||||
this->mqtt_server = new char[32];
|
||||
strcpy(mqtt_server, mqtt_config.mqtt_server);
|
||||
mqtt_port = mqtt_config.mqtt_port;
|
||||
if (mqtt_user != nullptr) {
|
||||
delete[] mqtt_user;
|
||||
}
|
||||
this->mqtt_user = new char[32];
|
||||
strcpy(mqtt_user, mqtt_config.mqtt_user);
|
||||
if (mqtt_password != nullptr) {
|
||||
delete[] mqtt_password;
|
||||
}
|
||||
this->mqtt_password = new char[32];
|
||||
strcpy(mqtt_password, mqtt_config.mqtt_password);
|
||||
mqtt_useauth = mqtt_config.mqtt_useauth;
|
||||
strcpy(base_topic, mqtt_config.base_topic);
|
||||
}
|
||||
|
||||
void ESPMegaIoT::bindEthernetInterface(ETHClass *ethernetIface)
|
||||
{
|
||||
this->ethernetIface = ethernetIface;
|
||||
}
|
||||
|
||||
IoTComponent* ESPMegaIoT::getComponent(uint8_t card_id)
|
||||
{
|
||||
return components[card_id];
|
||||
}
|
|
@ -33,12 +33,14 @@ struct MqttConfig
|
|||
char mqtt_user[32];
|
||||
char mqtt_password[32];
|
||||
bool mqtt_useauth;
|
||||
char base_topic[32];
|
||||
};
|
||||
|
||||
class ESPMegaIoT
|
||||
{
|
||||
public:
|
||||
ESPMegaIoT();
|
||||
~ESPMegaIoT();
|
||||
void intr_begin(ExpansionCard *cards[]);
|
||||
void loop();
|
||||
void registerCard(uint8_t card_id);
|
||||
|
@ -71,6 +73,8 @@ public:
|
|||
void registerRelativeMqttCallback(void (*callback)(char *, char *));
|
||||
void registerSubscribeCallback(void (*callback)(void));
|
||||
void setBaseTopic(char *base_topic);
|
||||
void bindEthernetInterface(ETHClass *ethernetIface);
|
||||
IoTComponent* getComponent(uint8_t card_id);
|
||||
IPAddress getETHIp();
|
||||
|
||||
private:
|
||||
|
@ -105,4 +109,5 @@ private:
|
|||
bool mqtt_useauth;
|
||||
bool mqtt_connected;
|
||||
NetworkConfig network_config;
|
||||
ETHClass *ethernetIface;
|
||||
};
|
|
@ -1,12 +1,5 @@
|
|||
#include <IoTComponent.hpp>
|
||||
|
||||
bool IoTComponent::begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic) {
|
||||
this->card_id = card_id;
|
||||
this->mqtt = mqtt;
|
||||
this->base_topic = base_topic;
|
||||
return true;
|
||||
}
|
||||
|
||||
void IoTComponent::setMqttClient(PubSubClient *mqtt) {
|
||||
this->mqtt = mqtt;
|
||||
}
|
||||
|
@ -18,7 +11,6 @@ void IoTComponent::publishRelative(const char *topic, const char *payload) {
|
|||
}
|
||||
|
||||
void IoTComponent::subscribeRelative(const char *topic) {
|
||||
Serial.println("Subscribe relative");
|
||||
char absolute_topic[50];
|
||||
sprintf(absolute_topic, "%s/%02d/%s", base_topic, card_id, topic);
|
||||
mqtt->subscribe(absolute_topic);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <PubSubClient.h>
|
||||
class IoTComponent {
|
||||
public:
|
||||
bool begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic);
|
||||
virtual bool begin(uint8_t card_id, ExpansionCard *card, PubSubClient *mqtt, char *base_topic);
|
||||
virtual void handleMqttMessage(char *topic, char *payload);
|
||||
void setMqttClient(PubSubClient *mqtt);
|
||||
virtual void publishReport();
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
#include <ESPMegaPRO_OOP.hpp>
|
||||
#include <ETH.h>
|
||||
|
||||
ESPMegaPRO espmega = ESPMegaPRO();
|
||||
|
||||
void input_change_callback(uint8_t pin, uint8_t value) {
|
||||
Serial.print("Input change callback: ");
|
||||
Serial.print(pin);
|
||||
Serial.print(" ");
|
||||
Serial.println(value);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
espmega.begin();
|
||||
espmega.enableIotModule();
|
||||
ETH.begin();
|
||||
espmega.iot.bindEthernetInterface(Ð);
|
||||
NetworkConfig config = {
|
||||
.ip = {192, 168, 0, 11},
|
||||
.gateway = {192, 168, 0, 1},
|
||||
|
@ -18,17 +28,28 @@ void setup() {
|
|||
strcpy(config.ssid, "ssid");
|
||||
strcpy(config.password, "password");
|
||||
strcpy(config.hostname, "espmega");
|
||||
Serial.println("Setting network config");
|
||||
espmega.iot.setNetworkConfig(config);
|
||||
Serial.println("Connecting to network");
|
||||
espmega.iot.connectNetwork();
|
||||
Serial.println("Begin MQTT Modules");
|
||||
MqttConfig mqtt_config = {
|
||||
.mqtt_port = 1883,
|
||||
.mqtt_useauth = false
|
||||
};
|
||||
Serial.println("Setting MQTT Server");
|
||||
strcpy(mqtt_config.mqtt_server, "192.168.0.26");
|
||||
strcpy(mqtt_config.base_topic, "/espmegaoop");
|
||||
Serial.println("Loading MQTT Config Struct to IoT Module");
|
||||
espmega.iot.setMqttConfig(mqtt_config);
|
||||
Serial.println("Connecting to MQTT");
|
||||
espmega.iot.connectToMqtt();
|
||||
Serial.println("Registering cards");
|
||||
espmega.iot.registerCard(0);
|
||||
espmega.iot.registerCard(1);
|
||||
Serial.println("Initialization Routine Complete");
|
||||
((DigitalInputIoT*)espmega.iot.getComponent(0)) -> registerChangeCallback(input_change_callback);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
|
Loading…
Reference in New Issue