diff --git a/include/hasp_conf.h b/include/hasp_conf.h index a14b936f..96b88a60 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -85,6 +85,10 @@ #include "hasp_ota.h" #endif +#if HASP_USE_TASMOTA_SLAVE>0 +#include "hasp_slave.h" +#endif + #endif #ifndef FPSTR diff --git a/lib/lvgl b/lib/lvgl index 549c75c0..85f281bd 160000 --- a/lib/lvgl +++ b/lib/lvgl @@ -1 +1 @@ -Subproject commit 549c75c07fbabc5c6799ef5d676875eadd5874e6 +Subproject commit 85f281bd3b4a6cb60381ff3d8a73534748e7d079 diff --git a/src/hasp_debug.cpp b/src/hasp_debug.cpp index 9a7192ba..449c1e3b 100644 --- a/src/hasp_debug.cpp +++ b/src/hasp_debug.cpp @@ -334,8 +334,10 @@ void debugPreSetup(JsonObject settings) if(baudrate >= 9600u) { /* the baudrates are stored divided by 10 */ #ifdef STM32_CORE_VERSION_MAJOR - // Serial.setRx(PA3); // User Serial2 - // Serial.setTx(PA2); + #ifndef STM32_SERIAL1 // Define what Serial port to use for log output + Serial.setRx(PA3); // User Serial2 + Serial.setTx(PA2); + #endif #endif Serial.begin(baudrate); /* prepare for possible serial debug */ delay(10); diff --git a/src/hasp_dispatch.cpp b/src/hasp_dispatch.cpp index d4965ce2..a93a485e 100644 --- a/src/hasp_dispatch.cpp +++ b/src/hasp_dispatch.cpp @@ -52,11 +52,10 @@ void dispatchOutput(int output, bool state) #if defined(ARDUINO_ARCH_ESP32) ledcWrite(99, state ? 1023 : 0); // ledChannel and value -#elif defined(ARDUINO_ARCH_ESP8266) - analogWrite(pin, state ? 1023 : 0); +#elif defined(STM32_CORE_VERSION) + digitalWrite(HASP_OUTPUT_PIN, state); #else - pinMode (PE0, OUTPUT); - digitalWrite(PE0, state ? 1 : 0); + analogWrite(pin, state ? 1023 : 0); #endif } } @@ -99,7 +98,10 @@ void dispatchAttribute(String strTopic, const char * payload) { if(strTopic.startsWith("p[")) { dispatchButtonAttribute(strTopic, payload); +<<<<<<< HEAD +======= +>>>>>>> 408b27b8155bd5f1c11900503df88956925fa6bd } else if(strTopic == F("page")) { dispatchPage(payload); @@ -137,9 +139,12 @@ void dispatchPage(String strPageid) String strPage((char *)0); strPage.reserve(128); strPage = haspGetPage(); -#if HASP_USE_MQTT +#if HASP_USE_MQTT > 0 mqtt_send_state(F("page"), strPage.c_str()); #endif +#if HASP_USE_TASMOTA_SLAVE > 0 + slave_send_state(F("page"), strPage.c_str()); +#endif } void dispatchClearPage(String strPageid) @@ -159,11 +164,16 @@ void dispatchDim(String strDimLevel) if(strDimLevel.length() != 0) guiSetDim(strDimLevel.toInt()); dispatchPrintln(F("DIM"), strDimLevel); -#if HASP_USE_MQTT +#if HASP_USE_MQTT > 0 char buffer[8]; itoa(guiGetDim(), buffer, DEC); mqtt_send_state(F("dim"), buffer); #endif +#if HASP_USE_TASMOTA_SLAVE > 0 + char buffer[8]; + itoa(guiGetDim(), buffer, DEC); + slave_send_state(F("dim"), buffer); +#endif } void dispatchBacklight(String strPayload) @@ -176,9 +186,13 @@ void dispatchBacklight(String strPayload) // Return the current state strPayload = getOnOff(guiGetBacklight()); -#if HASP_USE_MQTT +#if HASP_USE_MQTT > 0 mqtt_send_state(F("light"), strPayload.c_str()); #endif +#if HASP_USE_TASMOTA_SLAVE > 0 + slave_send_state(F("light"), strPayload.c_str()); +#endif + } void dispatchCommand(String cmnd) @@ -265,8 +279,10 @@ void dispatchJsonl(char * payload) void dispatchIdle(const char * state) { -#if HASP_USE_MQTT>0 +#if HASP_USE_MQTT > 0 mqtt_send_state(F("idle"), state); +#elif HASP_USE_TASMOTA_SLAVE > 0 + slave_send_state(F("idle"), state); #else Log.notice(F("OUT: idle = %s"), state); #endif @@ -275,11 +291,11 @@ void dispatchIdle(const char * state) void dispatchReboot(bool saveConfig) { if(saveConfig) configWriteConfig(); -#if HASP_USE_MQTT>0 +#if HASP_USE_MQTT > 0 mqttStop(); // Stop the MQTT Client first #endif debugStop(); -#if HASP_USE_WIFI>0 +#if HASP_USE_WIFI > 0 wifiStop(); #endif Log.verbose(F("-------------------------------------")); @@ -295,6 +311,9 @@ void dispatch_button(uint8_t id, const char * event) #else Log.notice(F("OUT: input%d = %s"), id, event); #endif +#if HASP_USE_TASMOTA_SLAVE + slave_send_input(id, event); +#endif } void dispatchWebUpdate(const char * espOtaUrl) @@ -309,6 +328,8 @@ void IRAM_ATTR dispatch_obj_attribute_str(uint8_t pageid, uint8_t btnid, const c { #if HASP_USE_MQTT > 0 mqtt_send_obj_attribute_str(pageid, btnid, attribute, data); +#elif HASP_USE_TASMOTA_SLAVE > 0 + slave_send_obj_attribute_str(pageid, btnid, attribute, data); #else Log.notice(F("OUT: json = {\"p[%u].b[%u].%s\":\"%s\"}"), pageid, btnid, attribute, data); #endif @@ -357,14 +378,14 @@ void dispatchConfig(const char * topic, const char * payload) haspGetConfig(settings); } -#if HASP_USE_WIFI +#if HASP_USE_WIFI > 0 else if(strcmp_P(topic, PSTR("wifi")) == 0) { if(update) wifiSetConfig(settings); else wifiGetConfig(settings); } -#if HASP_USE_MQTT +#if HASP_USE_MQTT > 0 else if(strcmp_P(topic, PSTR("mqtt")) == 0) { if(update) mqttSetConfig(settings); @@ -372,11 +393,11 @@ void dispatchConfig(const char * topic, const char * payload) mqttGetConfig(settings); } #endif -#if HASP_USE_TELNET +#if HASP_USE_TELNET > 0 // else if(strcmp_P(topic, PSTR("telnet")) == 0) // telnetGetConfig(settings[F("telnet")]); #endif -#if HASP_USE_MDNS +#if HASP_USE_MDNS > 0 else if(strcmp_P(topic, PSTR("mdns")) == 0) { if(update) mdnsSetConfig(settings); @@ -384,7 +405,7 @@ void dispatchConfig(const char * topic, const char * payload) mdnsGetConfig(settings); } #endif -#if HASP_USE_HTTP +#if HASP_USE_HTTP > 0 else if(strcmp_P(topic, PSTR("http")) == 0) { if(update) httpSetConfig(settings); @@ -398,8 +419,10 @@ void dispatchConfig(const char * topic, const char * payload) if(!update) { settings.remove(F("pass")); // hide password in output size_t size = serializeJson(doc, buffer, sizeof(buffer)); -#if HASP_USE_MQTT +#if HASP_USE_MQTT > 0 mqtt_send_state(F("config"), buffer); +#elif HASP_USE_TASMOTA > 0 + slave_send_state(F("config"), buffer); #else Log.notice(F("OUT: config %s = %s"),topic,buffer); #endif diff --git a/src/hasp_gpio.cpp b/src/hasp_gpio.cpp index 1ab5cefb..4094d7e6 100644 --- a/src/hasp_gpio.cpp +++ b/src/hasp_gpio.cpp @@ -7,4 +7,8 @@ void gpioSetup() pinMode(D1, OUTPUT); pinMode(D2, INPUT_PULLUP); #endif +#if defined(STM32_CORE_VERSION) + pinMode(HASP_OUTPUT_PIN, OUTPUT); + pinMode(HASP_INPUT_PIN, INPUT_PULLUP); +#endif } \ No newline at end of file diff --git a/src/hasp_gui.cpp b/src/hasp_gui.cpp index d590718f..337f8761 100644 --- a/src/hasp_gui.cpp +++ b/src/hasp_gui.cpp @@ -937,6 +937,7 @@ bool guiGetConfig(const JsonObject & settings) v.set(calData[i]); } else { changed = true; + tft.setTouch(calData); } i++; } @@ -947,6 +948,8 @@ bool guiGetConfig(const JsonObject & settings) for(uint8_t i = 0; i < 5; i++) { array.add(calData[i]); } + changed = true; + tft.setTouch(calData); } if(changed) configOutput(settings); @@ -995,14 +998,13 @@ bool guiSetConfig(const JsonObject & settings) } if(calData[0] != 0 || calData[1] != 65535 || calData[2] != 0 || calData[3] != 65535) { - Log.trace(F("calData set [%u, %u, %u, %u, %u]"), calData[0], calData[1], calData[2], calData[3], - calData[4]); + Log.trace(F("calData set [%u, %u, %u, %u, %u]"), calData[0], calData[1], calData[2], calData[3],calData[4]); oobeSetAutoCalibrate(false); } else { Log.notice(F("First Touch Calibration enabled")); oobeSetAutoCalibrate(true); } - + if (status) tft.setTouch(calData); changed |= status; } diff --git a/src/hasp_slave.cpp b/src/hasp_slave.cpp new file mode 100644 index 00000000..0fc479ef --- /dev/null +++ b/src/hasp_slave.cpp @@ -0,0 +1,147 @@ +/********************* + * INCLUDES + *********************/ +#include "hasp_slave.h" +#include +#include "ArduinoJson.h" +#include "ArduinoLog.h" +#include "hasp_dispatch.h" +#include "hasp_gui.h" +#include "tasmotaSlave.h" + +// set RX and TX pins +HardwareSerial Serial2(PD6, PD5); +TasmotaSlave slave(&Serial2); + +#define slaveNodeTopic "hasp/" + +unsigned long updateLedTimer = 0; // timer in msec for tele mqtt send +unsigned long updatLedPeriod = 1000; // timer in msec for tele mqtt send + +bool ledstate = false; + + +void IRAM_ATTR slave_send_state(const __FlashStringHelper * subtopic, const char * payload) +{ + // page = 0 + // p[0].b[0].attr = abc + // dim = 100 + // idle = 0/1 + // light = 0/1 + // brightness = 100 + + char cBuffer[strlen(payload) + 64]; + memset(cBuffer, 0 ,sizeof(cBuffer)); + snprintf(cBuffer, sizeof(cBuffer), PSTR("publish %sstate/%s %s"), slaveNodeTopic ,subtopic, payload); + slave.ExecuteCommand((char*)cBuffer); + + // Log after char buffers are cleared + Log.notice(F("TAS PUB: %sstate/%S = %s"), slaveNodeTopic, subtopic, payload); +} + +void IRAM_ATTR slave_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data) +{ + char cBuffer[192]; + memset(cBuffer, 0 ,sizeof(cBuffer)); + snprintf_P(cBuffer, sizeof(cBuffer), PSTR("publish %sstate/json {\"p[%u].b[%u].%s\":\"%s\"}"), slaveNodeTopic, pageid, btnid, attribute, data); + slave.ExecuteCommand((char*)cBuffer); + // Log after char buffers are cleared + Log.notice(F("TAS PUB: %sstate/json = {\"p[%u].b[%u].%s\":\"%s\"}"), slaveNodeTopic, pageid, btnid, attribute, data); +} + +void slave_send_input(uint8_t id, const char * payload) +{ + // Log.trace(F("MQTT TST: %sstate/input%u = %s"), mqttNodeTopic, id, payload); // to be removed + + char cBuffer[strlen(payload) + 64]; + memset(cBuffer, 0 ,sizeof(cBuffer)); + snprintf_P(cBuffer, sizeof(cBuffer), PSTR("publish %sstate/input%u %s"), slaveNodeTopic, id, payload); + slave.ExecuteCommand((char*)cBuffer); + + // Log after char buffers are cleared + Log.notice(F("TAS PUB: %sstate/input%u = %s"), slaveNodeTopic, id, payload); +} + +// void slave_send_statusupdate() +// { // Periodically publish a JSON string indicating system status +// char data[3 * 128]; +// { +// char buffer[128]; +// snprintf_P(data, sizeof(data), PSTR("{\"status\":\"available\",\"version\":\"%s\",\"uptime\":%lu,"), +// haspGetVersion().c_str(), long(millis() / 1000)); +// strcat(buffer, data); +// snprintf_P(buffer, sizeof(buffer), PSTR("\"heapFree\":%u,\"heapFrag\":%u,\"espCore\":\"%s\","), +// ESP.getFreeHeap(), halGetHeapFragmentation(), halGetCoreVersion().c_str()); +// strcat(data, buffer); +// snprintf_P(buffer, sizeof(buffer), PSTR("\"espCanUpdate\":\"false\",\"page\":%u,\"numPages\":%u}"), +// haspGetPage(), (HASP_NUM_PAGES)); +// strcat(data, buffer); +// snprintf_P(buffer, sizeof(buffer), PSTR("\"tftDriver\":\"%s\",\"tftWidth\":%u,\"tftHeight\":%u}"), +// tftDriverName().c_str(), (TFT_WIDTH), (TFT_HEIGHT)); +// strcat(data, buffer); +// } +// slave_send_state(F("statusupdate"), data); +// debugLastMillis = millis(); +// } + +void TASMO_DATA_RECEIVE(char *data) +{ + Log.verbose(F("TAS: Slave IN [%s]"), data); + + char slvCmd[20],slvVal[60]; + memset(slvCmd, 0 ,sizeof(slvCmd)); + memset(slvVal, 0 ,sizeof(slvVal)); + sscanf(data,"%s %s", slvCmd, slvVal); + + Log.verbose(F("TAS: Cmd[%s] Val[%s]"), slvCmd, slvVal); + + if (!strcmp(slvCmd, "calData")){ + if (strlen(slvVal) != 0) { + char cBuffer[strlen(slvVal) + 24]; + memset(cBuffer, 0 ,sizeof(cBuffer)); + snprintf_P(cBuffer, sizeof(cBuffer), PSTR("{'calibration':[%s]}"), slvVal); + dispatchConfig("gui",cBuffer); + } else { + dispatchConfig("gui",""); + } + } else if (!strcmp(slvCmd, "jsonl")) { + dispatchJsonl(slvVal); + } else { + char cBuffer[strlen(data)+1]; + snprintf_P(cBuffer, sizeof(cBuffer), PSTR("%s=%s"), slvCmd, slvVal); + dispatchCommand(cBuffer); + } +} + +void TASMO_EVERY_SECOND(void) +{ + if (ledstate) { + ledstate = false; + digitalWrite(HASP_OUTPUT_PIN, 1); + // Log.verbose(F("LED OFF")); + } else { + ledstate = true; + digitalWrite(HASP_OUTPUT_PIN, 0); + // Log.verbose(F("LED ON")); + } +} + +void slaveSetup() +{ + Serial2.begin(HASP_SLAVE_SPEED); + // slave.attach_FUNC_EVERY_SECOND(TASMO_EVERY_SECOND); + slave.attach_FUNC_COMMAND_SEND(TASMO_DATA_RECEIVE); + + Log.notice(F("TAS: HASP SLAVE LOADED")); +} + +void slaveLoop(void) +{ + slave.loop(); + // demo code to run the led without tasmota + // if ((millis() - updateLedTimer) >= updatLedPeriod) { + // updateLedTimer = millis(); + // TASMO_EVERY_SECOND(); + // } + +} \ No newline at end of file diff --git a/src/hasp_slave.h b/src/hasp_slave.h new file mode 100644 index 00000000..89db9964 --- /dev/null +++ b/src/hasp_slave.h @@ -0,0 +1,20 @@ +#ifndef HASP_SLAVE_H +#define HASP_SLAVE_H + +#include "ArduinoJson.h" + +#define HASP_SLAVE_SPEED 38400 + +void TASMO_EVERY_SECOND(void); +void TASMO_DATA_RECEIVE(char *data); +void IRAM_ATTR slave_send_state(const __FlashStringHelper * subtopic, const char * payload); +void IRAM_ATTR slave_send_obj_attribute_str(uint8_t pageid, uint8_t btnid, const char * attribute, const char * data); +void slave_send_input(uint8_t id, const char * payload); +void slave_send_statusupdate(); + + +void slaveSetup(); +void slaveLoop(void); + + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5bb44c72..020416c5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -80,6 +80,10 @@ void setup() buttonSetup(); #endif +#if HASP_USE_TASMOTA_SLAVE + slaveSetup(); +#endif + mainLastLoopTime = millis() - 1000; // reset loop counter } @@ -132,6 +136,10 @@ void loop() #endif // WIFI +#if HASP_USE_TASMOTA_SLAVE + slaveLoop(); +#endif // TASMOTASLAVE + // Every Second Loop if(millis() - mainLastLoopTime >= 1000) { /* Run Every Second */