diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaIoT.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaIoT.cpp index 0655287..2384bfc 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaIoT.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/ESPMegaIoT.cpp @@ -11,6 +11,9 @@ ESPMegaIoT::ESPMegaIoT() : mqtt(tcpClient) } active = false; mqtt_connected = false; + this->user_mqtt_callback = nullptr; + this->user_relative_mqtt_callback = nullptr; + this->user_subscribe_callback = nullptr; } ESPMegaIoT::~ESPMegaIoT() @@ -177,6 +180,12 @@ bool ESPMegaIoT::connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt 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_user == nullptr || mqtt_password == nullptr || strlen(mqtt_user) == 0 || strlen(mqtt_password) == 0) + { + mqtt_connected = false; + ESP_LOGE("ESPMegaIoT", "MQTT Connection failed: Username or password not set but MQTT use_auth is true"); + return false; + } if (mqtt.connect(client_id, mqtt_user, mqtt_password)) { sessionKeepAlive(); @@ -197,13 +206,18 @@ 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) { + ESP_LOGD("ESPMegaIoT", "Setting MQTT server to %s:%d", mqtt_server, mqtt_port); mqtt.setServer(mqtt_server, mqtt_port); auto boundCallback = std::bind(&ESPMegaIoT::mqttCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + ESP_LOGD("ESPMegaIoT", "Binding MQTT callback"); mqtt.setCallback(boundCallback); if (mqtt.connect(client_id)) { + ESP_LOGD("ESPMegaIoT", "MQTT Connected, Calling session keep alive"); sessionKeepAlive(); + ESP_LOGD("ESPMegaIoT", "Subscribing to topics"); mqttSubscribe(); + ESP_LOGD("ESPMegaIoT", "Publishing reports"); // Publish all cards for (int i = 0; i < 255; i++) { @@ -212,7 +226,7 @@ bool ESPMegaIoT::connectToMqtt(char *client_id, char *mqtt_server, uint16_t mqtt components[i]->publishReport(); } } - ESP_LOGI("ESPMegaIoT", "MQTT Connected"); + ESP_LOGI("ESPMegaIoT", "MQTT Connected OK."); mqtt_connected = true; return true; } @@ -234,16 +248,22 @@ void ESPMegaIoT::registerMqttCallback(void (*callback)(char *, char *)) } void ESPMegaIoT::mqttSubscribe() { - if (user_subscribe_callback != NULL) + ESP_LOGD("ESPMegaIoT", "Begin MQTT Subscription"); + if (user_subscribe_callback != nullptr) { + ESP_LOGD("ESPMegaIoT", "Subscribing user callback"); user_subscribe_callback(); + mqtt.loop(); } // Subscribe to all topics for (int i = 0; i < 255; i++) { + ESP_LOGV("ESPMegaIoT","Scanning component %d", i); if (components[i] != NULL) { + ESP_LOGD("ESPMegaIoT","Subscribing component %d", i); components[i]->subscribe(); + mqtt.loop(); } } } @@ -292,6 +312,7 @@ void ESPMegaIoT::publishRelative(char *topic, char *payload) char absolute_topic[100]; sprintf(absolute_topic, "%s/%s", base_topic, topic); mqtt.publish(absolute_topic, payload); + mqtt.loop(); } void ESPMegaIoT::subscribeRelative(char *topic) @@ -299,6 +320,7 @@ void ESPMegaIoT::subscribeRelative(char *topic) char absolute_topic[100]; sprintf(absolute_topic, "%s/%s", base_topic, topic); mqtt.subscribe(absolute_topic); + mqtt.loop(); } void ESPMegaIoT::registerSubscribeCallback(void (*callback)(void)) @@ -319,12 +341,12 @@ void ESPMegaIoT::loadNetworkConfig() network_config.subnet = fram->read32(IOT_FRAM_ADDRESS + 8); network_config.dns1 = fram->read32(IOT_FRAM_ADDRESS + 12); network_config.dns2 = fram->read32(IOT_FRAM_ADDRESS + 16); - fram->read(IOT_FRAM_ADDRESS + 20, (uint8_t*)network_config.hostname, 32); + fram->read(IOT_FRAM_ADDRESS + 20, (uint8_t *)network_config.hostname, 32); network_config.useStaticIp = fram->read8(IOT_FRAM_ADDRESS + 52); network_config.useWifi = fram->read8(IOT_FRAM_ADDRESS + 53); network_config.wifiUseAuth = fram->read8(IOT_FRAM_ADDRESS + 54); - fram->read(IOT_FRAM_ADDRESS + 55, (uint8_t*)network_config.ssid, 32); - fram->read(IOT_FRAM_ADDRESS + 87, (uint8_t*)network_config.password, 32); + fram->read(IOT_FRAM_ADDRESS + 55, (uint8_t *)network_config.ssid, 32); + fram->read(IOT_FRAM_ADDRESS + 87, (uint8_t *)network_config.password, 32); } void ESPMegaIoT::saveNetworkConfig() @@ -335,13 +357,12 @@ void ESPMegaIoT::saveNetworkConfig() fram->write32(IOT_FRAM_ADDRESS + 8, network_config.subnet); fram->write32(IOT_FRAM_ADDRESS + 12, network_config.dns1); fram->write32(IOT_FRAM_ADDRESS + 16, network_config.dns2); - fram->write(IOT_FRAM_ADDRESS + 20, (uint8_t*)network_config.hostname, 32); + fram->write(IOT_FRAM_ADDRESS + 20, (uint8_t *)network_config.hostname, 32); fram->write8(IOT_FRAM_ADDRESS + 52, network_config.useStaticIp); fram->write8(IOT_FRAM_ADDRESS + 53, network_config.useWifi); fram->write8(IOT_FRAM_ADDRESS + 54, network_config.wifiUseAuth); - fram->write(IOT_FRAM_ADDRESS + 55, (uint8_t*)network_config.ssid, 32); - fram->write(IOT_FRAM_ADDRESS + 87, (uint8_t*)network_config.password, 32); - + fram->write(IOT_FRAM_ADDRESS + 55, (uint8_t *)network_config.ssid, 32); + fram->write(IOT_FRAM_ADDRESS + 87, (uint8_t *)network_config.password, 32); } void ESPMegaIoT::ethernetBegin() @@ -354,29 +375,35 @@ void ESPMegaIoT::loadMqttConfig() // Load the mqtt config from FRAM // We skip bytes 119-127 because they are reserved for the network config mqtt_config.mqtt_port = fram->read16(IOT_FRAM_ADDRESS + 128); - fram->read(IOT_FRAM_ADDRESS + 130, (uint8_t*)mqtt_config.mqtt_server, 32); - fram->read(IOT_FRAM_ADDRESS + 162, (uint8_t*)mqtt_config.mqtt_user, 32); - fram->read(IOT_FRAM_ADDRESS + 194, (uint8_t*)mqtt_config.mqtt_password, 32); + fram->read(IOT_FRAM_ADDRESS + 130, (uint8_t *)mqtt_config.mqtt_server, 32); + fram->read(IOT_FRAM_ADDRESS + 162, (uint8_t *)mqtt_config.mqtt_user, 32); + fram->read(IOT_FRAM_ADDRESS + 194, (uint8_t *)mqtt_config.mqtt_password, 32); mqtt_config.mqtt_useauth = fram->read8(IOT_FRAM_ADDRESS + 226); - fram->read(IOT_FRAM_ADDRESS + 227, (uint8_t*)mqtt_config.base_topic, 32); + fram->read(IOT_FRAM_ADDRESS + 227, (uint8_t *)mqtt_config.base_topic, 32); } void ESPMegaIoT::saveMqttConfig() { fram->write16(IOT_FRAM_ADDRESS + 128, mqtt_config.mqtt_port); - fram->write(IOT_FRAM_ADDRESS + 130, (uint8_t*)mqtt_config.mqtt_server, 32); - fram->write(IOT_FRAM_ADDRESS + 162, (uint8_t*)mqtt_config.mqtt_user, 32); - fram->write(IOT_FRAM_ADDRESS + 194, (uint8_t*)mqtt_config.mqtt_password, 32); + fram->write(IOT_FRAM_ADDRESS + 130, (uint8_t *)mqtt_config.mqtt_server, 32); + fram->write(IOT_FRAM_ADDRESS + 162, (uint8_t *)mqtt_config.mqtt_user, 32); + fram->write(IOT_FRAM_ADDRESS + 194, (uint8_t *)mqtt_config.mqtt_password, 32); fram->write8(IOT_FRAM_ADDRESS + 226, mqtt_config.mqtt_useauth); - fram->write(IOT_FRAM_ADDRESS + 227, (uint8_t*)mqtt_config.base_topic, 32); + fram->write(IOT_FRAM_ADDRESS + 227, (uint8_t *)mqtt_config.base_topic, 32); } void ESPMegaIoT::connectToMqtt() { if (mqtt_config.mqtt_useauth) + { + ESP_LOGD("ESPMegaIoT", "Connecting to MQTT with auth"); this->connectToMqtt(network_config.hostname, mqtt_config.mqtt_server, mqtt_config.mqtt_port, mqtt_config.mqtt_user, mqtt_config.mqtt_password); + } else + { + ESP_LOGD("ESPMegaIoT", "Connecting to MQTT without auth"); this->connectToMqtt(network_config.hostname, mqtt_config.mqtt_server, mqtt_config.mqtt_port); + } } void ESPMegaIoT::connectNetwork() @@ -415,12 +442,12 @@ IoTComponent *ESPMegaIoT::getComponent(uint8_t card_id) return components[card_id]; } -NetworkConfig* ESPMegaIoT::getNetworkConfig() +NetworkConfig *ESPMegaIoT::getNetworkConfig() { return &network_config; } -MqttConfig* ESPMegaIoT::getMqttConfig() +MqttConfig *ESPMegaIoT::getMqttConfig() { return &mqtt_config; } diff --git a/ESPMegaPRO-firmware/lib/ESPMegaPRO/InternalDisplay.cpp b/ESPMegaPRO-firmware/lib/ESPMegaPRO/InternalDisplay.cpp index be1bb1f..20fa3f2 100644 --- a/ESPMegaPRO-firmware/lib/ESPMegaPRO/InternalDisplay.cpp +++ b/ESPMegaPRO-firmware/lib/ESPMegaPRO/InternalDisplay.cpp @@ -163,6 +163,9 @@ void InternalDisplay::saveMQTTConfig() // password_set -> a text input to set the mqtt password // topic_set -> a text input to set the mqtt base topic + // Send the stop bytes to flush the serial buffer + this->sendStopBytes(); + // Save the mqtt server if(!this->getStringToBuffer("mqttsv_set.txt", this->mqttConfig->mqtt_server, 16)) return; @@ -183,7 +186,10 @@ void InternalDisplay::saveMQTTConfig() return; // Save the mqtt use auth - this->mqttConfig->mqtt_useauth = this->getNumber("use_auth.val") == 1 ? true : false; + uint8_t use_auth = this->getNumber("use_auth.val"); + Serial.print("use_auth: "); + Serial.println(use_auth); + this->mqttConfig->mqtt_useauth = use_auth == 1 ? true : false; this->iot->saveMqttConfig(); ESP.restart(); } diff --git a/ESPMegaPRO-firmware/platformio.ini b/ESPMegaPRO-firmware/platformio.ini index ceed429..1fe009e 100644 --- a/ESPMegaPRO-firmware/platformio.ini +++ b/ESPMegaPRO-firmware/platformio.ini @@ -31,4 +31,4 @@ lib_deps = adafruit/Adafruit PWM Servo Driver Library@^2.4.1 https://github.com/me-no-dev/ESPAsyncWebServer.git #esphome/ESPAsyncWebServer-esphome@^3.1.0 monitor_speed = 115200 -build_flags = -DCORE_DEBUG_LEVEL=3 \ No newline at end of file +build_flags = -DCORE_DEBUG_LEVEL=1 \ No newline at end of file diff --git a/ESPMegaPRO-firmware/src/main.cpp b/ESPMegaPRO-firmware/src/main.cpp index a5cb2ff..8a07e59 100644 --- a/ESPMegaPRO-firmware/src/main.cpp +++ b/ESPMegaPRO-firmware/src/main.cpp @@ -3,16 +3,17 @@ #include #include - +// #define FRAM_DEBUG // Demo PLC firmware using the ESPMegaPRO OOP library ESPMegaPRO espmega = ESPMegaPRO(); const uint16_t irCode[15][4][4][1] = {0}; -const char* mode_names[] = {"Off", "Fan-only", "Cool"}; -const char* fan_speed_names[] = {"Auto", "Low", "Medium", "High"}; +const char *mode_names[] = {"Off", "Fan-only", "Cool"}; +const char *fan_speed_names[] = {"Auto", "Low", "Medium", "High"}; -size_t getInfraredCode(uint8_t mode, uint8_t fan_speed, uint8_t temperature, const uint16_t** codePtr) { +size_t getInfraredCode(uint8_t mode, uint8_t fan_speed, uint8_t temperature, const uint16_t **codePtr) +{ // Change the code pointer to point to the IR timing array *codePtr = &(irCode[mode][fan_speed][temperature][0]); return sizeof(irCode[mode][fan_speed][temperature]) / sizeof(uint16_t); @@ -25,19 +26,20 @@ AirConditioner ac = { .mode_names = mode_names, .fan_speeds = 4, .fan_speed_names = fan_speed_names, - .getInfraredCode = &getInfraredCode -}; + .getInfraredCode = &getInfraredCode}; ClimateCard climateCard = ClimateCard(14, ac); -void input_change_callback(uint8_t pin, uint8_t value) { +void input_change_callback(uint8_t pin, uint8_t value) +{ Serial.print("Input change callback: "); Serial.print(pin); Serial.print(" "); Serial.println(value); } -void setNetworkConfig() { +void setNetworkConfig() +{ NetworkConfig config = { .ip = {192, 168, 0, 11}, .gateway = {192, 168, 0, 1}, @@ -54,53 +56,70 @@ void setNetworkConfig() { Serial.println("Setting network config"); espmega.iot->setNetworkConfig(config); espmega.iot->saveNetworkConfig(); - } -void setMqttConfig() { +void setMqttConfig() +{ MqttConfig config = { .mqtt_port = 1883, - .mqtt_useauth = false - }; + .mqtt_useauth = false}; strcpy(config.mqtt_server, "192.168.0.26"); strcpy(config.base_topic, "/espmegaoop"); espmega.iot->setMqttConfig(config); espmega.iot->saveMqttConfig(); } -void setup() { +void setup() +{ + ESP_LOGI("Initializer", "Starting ESPMegaPRO OOP demo"); espmega.begin(); + ESP_LOGI("Initializer", "Enabling IOT module"); espmega.enableIotModule(); + ESP_LOGI("Initializer", "Enabling Ethernet"); ETH.begin(); + ESP_LOGI("Initializer", "Binding Ethernet to IOT module"); espmega.iot->bindEthernetInterface(Ð); + ESP_LOGI("Initializer", "Loading network config"); espmega.iot->loadNetworkConfig(); + ESP_LOGI("Initializer", "Connecting to network"); espmega.iot->connectNetwork(); + ESP_LOGI("Initializer", "Loading MQTT config"); espmega.iot->loadMqttConfig(); + ESP_LOGI("Initializer", "Connecting to MQTT"); espmega.iot->connectToMqtt(); + ESP_LOGI("Initializer", "Registering cards 0"); espmega.iot->registerCard(0); + ESP_LOGI("Initializer", "Registering cards 1"); espmega.iot->registerCard(1); + ESP_LOGI("Initializer", "Registering Input change callback"); espmega.inputs.registerCallback(input_change_callback); + ESP_LOGI("Initializer", "Installing climate card"); espmega.installCard(2, &climateCard); + ESP_LOGI("Initializer", "Binding climate card to FRAM"); climateCard.bindFRAM(&espmega.fram, 301); + ESP_LOGI("Initializer", "Loading climate card state from FRAM"); climateCard.loadStateFromFRAM(); + ESP_LOGI("Initializer", "Enabling climate card FRAM autosave"); climateCard.setFRAMAutoSave(true); + ESP_LOGI("Initializer", "Enabling internal display"); espmega.enableInternalDisplay(&Serial); + ESP_LOGI("Initializer", "Binding climate card to internal display"); espmega.display->bindClimateCard(&climateCard); } - - -// Every 20 seconds, dump FRAM 0-500 to serial -void loop() { +void loop() +{ espmega.loop(); - #ifdef FRAM_DEBUG +#ifdef FRAM_DEBUG + // Every 20 seconds, dump FRAM 0-500 to serial static uint32_t last_fram_dump = 0; - if (millis() - last_fram_dump >= 20000) { + if (millis() - last_fram_dump >= 20000) + { last_fram_dump = millis(); Serial.println("Dumping FRAM"); espmega.dumpFRAMtoSerial(0, 500); Serial.println("Dumping FRAM ASCII"); espmega.dumpFRAMtoSerialASCII(0, 500); } - #endif +#endif } \ No newline at end of file