working digital output card implementation
This commit is contained in:
parent
ca228f7cd0
commit
63a34afee3
|
@ -57,4 +57,16 @@ uint16_t DigitalOutputCard::getValue(uint8_t pin) {
|
|||
// Get type of card
|
||||
uint8_t DigitalOutputCard::getType() {
|
||||
return CARD_TYPE_DIGITAL_OUTPUT;
|
||||
}
|
||||
}
|
||||
|
||||
void DigitalOutputCard::setState(uint8_t pin, bool state) {
|
||||
this-> state_buffer[pin] = state;
|
||||
this->pwm.setPin(pin, state*value_buffer[pin]);
|
||||
}
|
||||
|
||||
void DigitalOutputCard::setValue(uint8_t pin, uint16_t value) {
|
||||
// If value is greater than 4095, set it to 4095
|
||||
if (value > 4095) value = 4095;
|
||||
this-> value_buffer[pin] = value;
|
||||
this->pwm.setPin(pin, state_buffer[pin]*value);
|
||||
}
|
||||
|
|
|
@ -32,9 +32,15 @@ public:
|
|||
// Dummy loop function
|
||||
void loop();
|
||||
// Set the output to the specified state
|
||||
// This function set both the state and the pwm value
|
||||
void digitalWrite(uint8_t pin, bool state);
|
||||
// Set the output to the specified pwm value
|
||||
// This function set both the state and the pwm value
|
||||
void analogWrite(uint8_t pin, uint16_t value);
|
||||
// Set the state of the specified pin
|
||||
void setState(uint8_t pin, bool state);
|
||||
// Set the pwm value of the specified pin
|
||||
void setValue(uint8_t pin, uint16_t value);
|
||||
// Get the state of the specified pin
|
||||
bool getState(uint8_t pin);
|
||||
// Get the pwm value of the specified pin
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
DigitalOutputIoT::DigitalOutputIoT() {
|
||||
this->state_report_topic = new char[10];
|
||||
this->value_report_topic = new char[10];
|
||||
this->digital_outputs_publish_enabled = true;
|
||||
}
|
||||
|
||||
DigitalOutputIoT::~DigitalOutputIoT() {
|
||||
|
@ -22,6 +23,8 @@ bool DigitalOutputIoT::begin(uint8_t card_id, ExpansionCard *card, PubSubClient
|
|||
this->set_value_length = strlen(SET_VALUE_TOPIC);
|
||||
this->state_length = strlen(STATE_TOPIC);
|
||||
this->value_length = strlen(VALUE_TOPIC);
|
||||
this->request_state_length = strlen(REQUEST_STATE_TOPIC);
|
||||
this->publish_enable_length = strlen(PUBLISH_ENABLE_TOPIC);
|
||||
strcpy(this->state_report_topic, "00/state");
|
||||
strcpy(this->value_report_topic, "00/value");
|
||||
return true;
|
||||
|
@ -36,10 +39,15 @@ 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) {
|
||||
|
@ -50,26 +58,35 @@ 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') {
|
||||
bool state = false;
|
||||
state = false;
|
||||
} else if (state_char == '1') {
|
||||
bool state = true;
|
||||
state = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
Serial.print("State: ");
|
||||
Serial.println(state);
|
||||
// Set the state
|
||||
card->digitalWrite(pin, state);
|
||||
card->setState(pin, state);
|
||||
publishDigitalOutputState(pin);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -80,21 +97,26 @@ 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
|
||||
uint16_t value = atoi(payload);
|
||||
// Set the value
|
||||
card->analogWrite(pin, value);
|
||||
card->setValue(pin, value);
|
||||
publishDigitalOutputValue(pin);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -105,11 +127,18 @@ 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;
|
||||
|
@ -119,7 +148,8 @@ bool DigitalOutputIoT::processRequestStateMessage(char *topic, char *payload, ui
|
|||
|
||||
void DigitalOutputIoT::publishDigitalOutputs() {
|
||||
if(!digital_outputs_publish_enabled) return;
|
||||
for(int i = 1; i <= 16; i++) {
|
||||
Serial.println("Publishing digital outputs");
|
||||
for(int i = 0; i < 16; i++) {
|
||||
publishDigitalOutput(i);
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +163,7 @@ void DigitalOutputIoT::publishDigitalOutputState(uint8_t pin) {
|
|||
if(!digital_outputs_publish_enabled) return;
|
||||
state_report_topic[0] = pin / 10 + '0';
|
||||
state_report_topic[1] = pin % 10 + '0';
|
||||
mqtt->publish(state_report_topic, card->getState(pin) ? "1" : "0");
|
||||
publishRelative(state_report_topic, card->getState(pin) ? "1" : "0");
|
||||
}
|
||||
|
||||
void DigitalOutputIoT::publishDigitalOutputValue(uint8_t pin) {
|
||||
|
@ -142,7 +172,7 @@ void DigitalOutputIoT::publishDigitalOutputValue(uint8_t pin) {
|
|||
value_report_topic[1] = pin % 10 + '0';
|
||||
char payload[5];
|
||||
sprintf(payload, "%d", card->getValue(pin));
|
||||
mqtt->publish(value_report_topic, payload);
|
||||
publishRelative(value_report_topic, payload);
|
||||
}
|
||||
|
||||
void DigitalOutputIoT::setDigitalOutputsPublishEnabled(bool enabled) {
|
||||
|
@ -177,13 +207,13 @@ void DigitalOutputIoT::subscribe() {
|
|||
char topic[20];
|
||||
Serial.println("Subscribe to all set state topics");
|
||||
// Subscribe to all set state topics
|
||||
for(int i = 1; i <= 16; i++) {
|
||||
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 = 1; i <= 16; i++) {
|
||||
for(int i = 0; i < 16; i++) {
|
||||
sprintf(topic, "%02d/set/value", i);
|
||||
subscribeRelative(topic);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,11 @@ 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,7 +99,7 @@ void ESPMegaIoT::registerCard(uint8_t card_id)
|
|||
if (mqtt_connected)
|
||||
{
|
||||
components[card_id]->subscribe();
|
||||
Serial.println("Back to register card");
|
||||
components[card_id]->publishReport();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -165,6 +169,14 @@ bool ESPMegaIoT::connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt
|
|||
{
|
||||
sessionKeepAlive();
|
||||
mqttSubscribe();
|
||||
// Publish all cards
|
||||
for (int i = 0; i < 255; i++)
|
||||
{
|
||||
if (components[i] != NULL)
|
||||
{
|
||||
components[i]->publishReport();
|
||||
}
|
||||
}
|
||||
mqtt_connected = true;
|
||||
return true;
|
||||
}
|
||||
|
@ -192,6 +204,15 @@ bool ESPMegaIoT::connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt
|
|||
sessionKeepAlive();
|
||||
Serial.println("Subscribing to topics");
|
||||
mqttSubscribe();
|
||||
Serial.println("Publishing all cards");
|
||||
// Publish all cards
|
||||
for (int i = 0; i < 255; i++)
|
||||
{
|
||||
if (components[i] != NULL)
|
||||
{
|
||||
components[i]->publishReport();
|
||||
}
|
||||
}
|
||||
mqtt_connected = true;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -4,16 +4,16 @@ void IoTComponent::setMqttClient(PubSubClient *mqtt) {
|
|||
this->mqtt = mqtt;
|
||||
}
|
||||
|
||||
void IoTComponent::publishRelative(char *topic, char *payload) {
|
||||
void IoTComponent::publishRelative(const char *topic, const char *payload) {
|
||||
char absolute_topic[100];
|
||||
sprintf(absolute_topic, "%s/%d/%s", base_topic, card_id, topic);
|
||||
sprintf(absolute_topic, "%s/%02d/%s", base_topic, card_id, topic);
|
||||
mqtt->publish(absolute_topic, payload);
|
||||
}
|
||||
|
||||
void IoTComponent::subscribeRelative(char *topic) {
|
||||
void IoTComponent::subscribeRelative(const char *topic) {
|
||||
Serial.println("Subscribe relative");
|
||||
char absolute_topic[50];
|
||||
sprintf(absolute_topic, "%s/%d/%s", base_topic, card_id, topic);
|
||||
sprintf(absolute_topic, "%s/%02d/%s", base_topic, card_id, topic);
|
||||
mqtt->subscribe(absolute_topic);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,11 +9,12 @@ class IoTComponent {
|
|||
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);
|
||||
void publishRelative(const char *topic, const char *payload);
|
||||
void subscribeRelative(const char *topic);
|
||||
PubSubClient *mqtt;
|
||||
uint8_t card_id;
|
||||
};
|
||||
|
|
|
@ -19,28 +19,14 @@ void setup()
|
|||
{
|
||||
// Initialize ESPMega
|
||||
espmega.begin();
|
||||
Serial.println("ESPMega initialized");
|
||||
Serial.println("Initializing ESPMega IoT");
|
||||
espmega.enableIotModule();
|
||||
Serial.println("ESPMega IoT module enabled");
|
||||
Serial.println("Setting static IP");
|
||||
Serial.println("Connecting to Ethernet");
|
||||
ETH.begin();
|
||||
ETH.config(ip, gateway, subnet);
|
||||
Serial.println("Static IP set");
|
||||
Serial.println("Begin MQTT Initialization Routine");
|
||||
Serial.println("Setting MQTT Base Topic");
|
||||
espmega.iot.setBaseTopic("/testmegaoop");
|
||||
Serial.println("Initializing MQTT");
|
||||
espmega.iot.connectToMqtt("espmega", "192.168.0.26", 1883);
|
||||
Serial.println("Publishing a test message");
|
||||
espmega.iot.publishRelative("test", "test");
|
||||
Serial.println("Subscribing to test topic");
|
||||
espmega.iot.subscribeRelative("test");
|
||||
Serial.println("Registering MQTT Callback");
|
||||
espmega.iot.registerMqttCallback(mqtt_callback);
|
||||
Serial.println("ESPMega IoT initialized");
|
||||
Serial.println("Enable IoT Module for Digital Output Card");
|
||||
espmega.iot.registerCard(1);
|
||||
espmega.iot.publishCard(1);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue