diff --git a/platformio.ini b/platformio.ini index 0074e59..1995297 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,6 +12,7 @@ platform = espressif32 board = wt32-eth01 framework = arduino +board_build.f_cpu = 240000000L lib_deps = siwats/ESPMegaPROR3@^1.3.0 knolleary/PubSubClient@^2.8 ivanseidel/ArduinoThread@^2.1.1 diff --git a/src/espmega_iot_core.cpp b/src/espmega_iot_core.cpp index 84e0817..0ff5efc 100644 --- a/src/espmega_iot_core.cpp +++ b/src/espmega_iot_core.cpp @@ -19,7 +19,6 @@ uint16_t MQTT_PORT = 0; WebServer otaserver(80); #endif bool standalone = true; -// #define MQTT_BASE_TOPIC "/espmega/ProR3" char MQTT_BASE_TOPIC[20]; uint8_t base_topic_length = 0; char STATE_REQUEST_TOPIC[40]; @@ -104,8 +103,7 @@ char PWM_VALUE_TOPIC[75]; char INPUTS_TOPIC[75]; WiFiClient eth; -PubSubClient mqtt_client(MQTT_SERVER, 1883, eth); -PubSubClientTools mqtt(mqtt_client); +PubSubClient mqtt(MQTT_SERVER, 1883, eth); #ifdef ENABLE_CLIMATE_MODULE DHTNEW env_sensor(DHT22_PIN); @@ -159,8 +157,9 @@ void setup() lcd_send_command("boot_state.txt=\"Network Initializing . . .\""); network_begin(); lcd_send_command("boot_state.txt=\"IoT Core Initializing . . .\""); - mqtt_client.setSocketTimeout(1000); + mqtt.setSocketTimeout(1000); eth.setTimeout(1); + mqtt.setCallback(&mqtt_callback); mqtt_connect(); lcd_send_command("boot_state.txt=\"Threads Initializing . . .\""); thread_initialization(); @@ -176,7 +175,7 @@ void setup() void loop() { virtual_interrupt_loop(); - mqtt_client.loop(); + mqtt.loop(); ESPMega_loop(); #ifdef ENABLE_IR_MODULE ir_loop(); @@ -243,7 +242,7 @@ void eeprom_retrieve_init() eeprom_mqtt_useauth_retrieve(); eeprom_mqtt_username_retrieve(); eeprom_mqtt_password_retrieve(); - mqtt_client.setServer(MQTT_SERVER, MQTT_PORT); + mqtt.setServer(MQTT_SERVER, MQTT_PORT); eeprom_basetopic_retrieve(); base_topic_length = strlen(MQTT_BASE_TOPIC) + 1; memcpy(STATE_REQUEST_TOPIC, MQTT_BASE_TOPIC, 20); @@ -465,15 +464,15 @@ void network_begin() void mqtt_connect() { - if (!mqtt_client.connected()) + if (!mqtt.connected()) { Serial.print("MQTT not connected, connecting . . .\n"); lcd_send_stop_bit(); if (MQTT_USE_AUTH) - mqtt_client.connect(HOSTNAME, MQTT_USERNAME, MQTT_PASSWORD); + mqtt.connect(HOSTNAME, MQTT_USERNAME, MQTT_PASSWORD); else - mqtt_client.connect(HOSTNAME); - if (mqtt_client.connected()) + mqtt.connect(HOSTNAME); + if (mqtt.connected()) { mqtt_subscribe(); Serial.print("MQTT connected\n"); @@ -509,15 +508,40 @@ void mqtt_subscribe() PWM_SET_VALUE_TOPIC[base_topic_length + 5] = (i % 10) + '0'; PWM_SET_STATE_TOPIC[base_topic_length + 4] = ((i - i % 10) / 10) + '0'; PWM_SET_STATE_TOPIC[base_topic_length + 5] = (i % 10) + '0'; - mqtt.subscribe(PWM_SET_STATE_TOPIC, pwm_state_callback); - mqtt.subscribe(PWM_SET_VALUE_TOPIC, pwm_value_callback); + mqtt.subscribe(PWM_SET_STATE_TOPIC); + mqtt.subscribe(PWM_SET_VALUE_TOPIC); } #ifdef ENABLE_CLIMATE_MODULE - mqtt.subscribe(AC_SET_FAN_TOPIC, ac_state_callback); - mqtt.subscribe(AC_SET_TEMPERATURE_TOPIC, ac_state_callback); - mqtt.subscribe(AC_SET_MODE_TOPIC, ac_state_callback); + mqtt.subscribe(AC_SET_FAN_TOPIC); + mqtt.subscribe(AC_SET_TEMPERATURE_TOPIC); + mqtt.subscribe(AC_SET_MODE_TOPIC); #endif - mqtt.subscribe(STATE_REQUEST_TOPIC, state_request_callback); + mqtt.subscribe(STATE_REQUEST_TOPIC); +} + +void mqtt_callback(char *topic, byte *payload, unsigned int length) +{ + uint8_t topic_length = strlen(topic); + char topic_trim[50]; + char payload_nt[length + 1]; + memcpy(payload_nt, payload, length); + payload_nt[length] = NULL; + strncpy(topic_trim, topic + base_topic_length - 1, topic_length); + if ((!strncmp(topic_trim, "/pwm/", 5)) && !strncmp(topic_trim + 7, "/set/state", 10)) + { + pwm_state_callback(topic_trim, topic_length, payload_nt, length); + } + else if ((!strncmp(topic_trim, "/pwm/", 5)) && !strncmp(topic_trim + 7, "/set/value", 10)) + { + pwm_value_callback(topic_trim, topic_length, payload_nt, length); + } else if(!strcmp(topic,STATE_REQUEST_TOPIC)) { + state_request_callback(); + } + else + { + ac_state_callback(topic, topic_length, payload_nt, length); + } + user_mqtt_callback(topic, topic_length, payload_nt, length); } void thread_initialization() @@ -536,27 +560,27 @@ void thread_initialization() user_timer_tick.setInterval(15000); } -void pwm_state_callback(String topic, String message) +void pwm_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length) { - int a = topic.charAt(base_topic_length + 4) - '0'; - int b = topic.charAt(base_topic_length + 5) - '0'; + int a = topic[5] - '0'; + int b = topic[6] - '0'; int id = 10 * a + b; - if (message.compareTo("on") == 0) + if (!strcmp(payload, "on")) { pwm_set_state(id, true); } - else if (message.compareTo("off") == 0) + else if (!strcmp(payload, "off")) { pwm_set_state(id, false); } } -void pwm_value_callback(String topic, String message) +void pwm_value_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length) { - int a = topic.charAt(base_topic_length + 4) - '0'; - int b = topic.charAt(base_topic_length + 5) - '0'; + int a = topic[5] - '0'; + int b = topic[6] - '0'; int id = 10 * a + b; - int value = message.toInt(); + int value = atoi(payload); pwm_set_value(id, value); } @@ -610,13 +634,15 @@ void publish_pwm_state(int id) PWM_VALUE_TOPIC[base_topic_length + 5] = (id % 10) + '0'; if (state == 1) { - mqtt_client.publish(PWM_STATE_TOPIC, "on"); + mqtt.publish(PWM_STATE_TOPIC, "on"); } else if (state == 0) { - mqtt_client.publish(PWM_STATE_TOPIC, "off"); + mqtt.publish(PWM_STATE_TOPIC, "off"); } - mqtt.publish(String(PWM_VALUE_TOPIC), String(value)); + char temp[6]; + itoa(value, temp, DEC); + mqtt.publish(PWM_VALUE_TOPIC, temp); } void pwm_set_state(int id, int state) @@ -723,10 +749,10 @@ void publish_input_state(int id, int state) { INPUTS_TOPIC[base_topic_length + 6] = ((id - id % 10) / 10) + '0'; INPUTS_TOPIC[base_topic_length + 7] = (id % 10) + '0'; - mqtt.publish(String(INPUTS_TOPIC), state ? "1" : "0"); + mqtt.publish(INPUTS_TOPIC, state ? "1" : "0"); } -void state_request_callback(String topic, String message) +void state_request_callback() { publish_input_states(); publish_pwm_states(); @@ -749,80 +775,79 @@ void ir_loop() #ifdef ENABLE_CLIMATE_MODULE void publish_ac_state() { - String temp = ""; switch (ac_mode) { case 0: - temp = "off"; + mqtt.publish(AC_MODE_TOPIC, "off"); break; case 1: - temp = "cool"; + mqtt.publish(AC_MODE_TOPIC, "cool"); break; case 2: - temp = "fan_only"; + mqtt.publish(AC_MODE_TOPIC, "fan_only"); default: break; } - mqtt.publish(String(AC_MODE_TOPIC), temp); - mqtt.publish(String(AC_TEMPERATURE_TOPIC), String(ac_temperature)); + char temp[5]; + itoa(ac_temperature, temp, DEC); + mqtt.publish(AC_TEMPERATURE_TOPIC, temp); switch (ac_fan_speed) { case 0: - temp = "auto"; + mqtt.publish(AC_FAN_TOPIC, "auto"); break; case 1: - temp = "high"; + mqtt.publish(AC_FAN_TOPIC, "high"); break; case 2: - temp = "med"; + mqtt.publish(AC_FAN_TOPIC, "medium"); break; case 3: - temp = "low"; + mqtt.publish(AC_FAN_TOPIC, "low"); break; } - mqtt.publish(String(AC_FAN_TOPIC), temp); } -void ac_state_callback(String topic, String message) +void ac_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length) { - if (topic.compareTo(String(AC_SET_TEMPERATURE_TOPIC)) == 0) + if (!strcmp(topic, AC_SET_TEMPERATURE_TOPIC)) { - int new_temp = message.toInt(); + int new_temp = atoi(payload); if (new_temp >= AC_MIN_TEMPERATURE && new_temp <= AC_MAX_TEMPERATURE) { ac_set_state(ac_mode, new_temp, ac_fan_speed); } } - else if (topic.compareTo(String(AC_SET_MODE_TOPIC)) == 0) + else if (!strcmp(topic, AC_SET_MODE_TOPIC)) { - if (message.compareTo("off") == 0) + if (!strcmp(payload, "off")) { ac_set_state(0, ac_temperature, ac_fan_speed); } - else if (message.compareTo("cool") == 0) + else if (!strcmp(payload, "cool")) { ac_set_state(1, ac_temperature, ac_fan_speed); } - else if (message.compareTo("fan_only") == 0) + else if (!strcmp(payload, "fan_only")) { ac_set_state(2, ac_temperature, ac_fan_speed); } } - else if (topic.compareTo(String(AC_SET_FAN_TOPIC)) == 0) + else if (!strcmp(topic, AC_SET_FAN_TOPIC)) { - if (message.compareTo("auto") == 0) + if (!strcmp(payload, "auto")) { ac_set_state(ac_mode, ac_temperature, 0); } - else if (message.compareTo("low") == 0) + else if (!strcmp(payload, "high")) { ac_set_state(ac_mode, ac_temperature, 1); } - else if (message.compareTo("med") == 0) + else if (!strcmp(payload, "medium")) { ac_set_state(ac_mode, ac_temperature, 2); } - else if (message.compareTo("high") == 0) + else if (!strcmp(payload, "low")) { ac_set_state(ac_mode, ac_temperature, 3); } @@ -859,7 +884,7 @@ void ac_set_state(int mode, int temperature, int fan_speed) IrSender.sendRaw(ir_code_off, sizeof(ir_code_off) / sizeof(ir_code_off[0]), NEC_KHZ); break; case 1: - IrSender.sendRaw(ir_code_cool[fan_speed][temperature], sizeof(ir_code_cool[fan_speed][temperature]) / sizeof(ir_code_cool[fan_speed][0]), NEC_KHZ); + IrSender.sendRaw(ir_code_cool[fan_speed][temperature], sizeof(ir_code_cool[fan_speed][temperature]) / sizeof(ir_code_cool[fan_speed][temperature][0]), NEC_KHZ); break; case 2: IrSender.sendRaw(ir_code_fan[fan_speed], sizeof(ir_code_fan[fan_speed]) / sizeof(ir_code_fan[fan_speed][0]), NEC_KHZ); @@ -877,10 +902,12 @@ void publish_env_state() case DHTLIB_OK: current_room_humid = env_sensor.getHumidity(); current_room_temp = env_sensor.getTemperature(); - mqtt.publish(String(AC_ROOM_TEMPERATURE_TOPIC), String(current_room_temp)); - mqtt_client.loop(); - mqtt.publish(String(AC_HUMIDITY_TOPIC), String(current_room_humid)); - mqtt_client.loop(); + char temp[5]; + dtostrf(current_room_temp, 0, 2, temp); + mqtt.publish(AC_ROOM_TEMPERATURE_TOPIC, temp); + dtostrf(current_room_humid, 0, 2, temp); + mqtt.publish(AC_HUMIDITY_TOPIC, temp); + mqtt.loop(); #ifdef ENABLE_INTERNAL_LCD if (lcd_current_page == 4) { @@ -892,10 +919,10 @@ void publish_env_state() #endif break; default: - mqtt.publish(String(AC_ROOM_TEMPERATURE_TOPIC), "ERROR"); - mqtt_client.loop(); - mqtt.publish(String(AC_HUMIDITY_TOPIC), "ERROR"); - mqtt_client.loop(); + mqtt.publish(AC_ROOM_TEMPERATURE_TOPIC, "ERROR"); + mqtt.loop(); + mqtt.publish(AC_HUMIDITY_TOPIC, "ERROR"); + mqtt.loop(); } } #endif diff --git a/src/espmega_iot_core.hpp b/src/espmega_iot_core.hpp index bf03bf5..42582ed 100644 --- a/src/espmega_iot_core.hpp +++ b/src/espmega_iot_core.hpp @@ -9,7 +9,6 @@ #endif #include #include -#include #include #include #ifdef ENABLE_IR_MODULE @@ -35,15 +34,16 @@ #endif #include "espmega_iot_timer.hpp" +void mqtt_callback(char* topic, byte* payload, unsigned int length); void virtual_interrupt_loop(); void virtual_interrupt_callback(int pin, int state); void network_begin(); void mqtt_connect(); void mqtt_subscribe(); void thread_initialization(); -void pwm_state_callback(String topic, String message); -void pwm_value_callback(String topic, String message); -void state_request_callback(String topic, String message); +void pwm_state_callback(char* topic, uint8_t topic_length, char* payload, unsigned int payload_length); +void pwm_value_callback(char* topic, uint8_t topic_length, char* payload, unsigned int payload_length); +void state_request_callback(); void io_begin(); void ir_loop(); @@ -66,7 +66,7 @@ void publish_env_state(); uint8_t ac_get_temperature(); uint8_t ac_get_mode(); uint8_t ac_get_fan_speed(); -void ac_state_callback(String topic, String message); +void ac_state_callback(char* topic, uint8_t topic_length, char* payload, unsigned int payload_length); void ac_set_state(int mode, int temperature, int fan_speed); void publish_input_states(); diff --git a/src/user_code.cpp b/src/user_code.cpp index 929235b..0af23b5 100644 --- a/src/user_code.cpp +++ b/src/user_code.cpp @@ -109,4 +109,8 @@ float adc2watts(uint16_t adc_value) float secondary_current = burden_voltage / BURDEN_RESISTANCE; float primary_current = secondary_current / RATIO; return primary_current * VOLTAGE; +} + +void user_mqtt_callback(char* topic, uint8_t topic_length, char* payload, unsigned int payload_length) { + } \ No newline at end of file diff --git a/src/user_code.hpp b/src/user_code.hpp index 7f65cf6..ece4efa 100644 --- a/src/user_code.hpp +++ b/src/user_code.hpp @@ -44,6 +44,7 @@ void bt0PopCallback(void *ptr); void user_state_request_callback(); float adc2watts(uint16_t adc_value); +void user_mqtt_callback(char* topic, uint8_t topic_length, char* payload, unsigned int payload_length); // ESPMega IoT Core Build-in Functions extern void pwm_set_state(int id, int state); @@ -60,5 +61,4 @@ extern uint8_t ac_get_temperature(); extern uint8_t ac_get_mode(); extern uint8_t ac_get_fan_speed(); extern bool standalone; -extern PubSubClient mqtt_client; -extern PubSubClientTools mqtt; \ No newline at end of file +extern PubSubClient mqtt; \ No newline at end of file