From bf873b67e50fbbda22b4b3c70a675955f5377de4 Mon Sep 17 00:00:00 2001 From: Thomas Popp <66408890+tspopp@users.noreply.github.com> Date: Sat, 15 Jun 2024 21:44:44 +0200 Subject: [PATCH] feat(aquadbg): more troubleshooting tooling (#27) --- TROUBLESHOOTING.md | 10 +- tools/AquaDebug/.clang-format | 137 ++++++++++++++++++ tools/AquaDebug/.gitignore | 2 + tools/AquaDebug/.idea/.gitignore | 8 + tools/AquaDebug/.idea/codeStyles/Project.xml | 7 + .../.idea/codeStyles/codeStyleConfig.xml | 5 + tools/AquaDebug/.idea/misc.xml | 17 +++ tools/AquaDebug/.idea/vcs.xml | 7 + tools/AquaDebug/README.md | 39 +++++ tools/AquaDebug/collect.py | 44 ++++++ .../AquaDebug/include/config/Configuration.h | 44 ++++++ .../include/config/ExampleConfiguration.h | 22 +++ tools/AquaDebug/include/handler/OTA.h | 19 +++ .../AquaDebug/include/mqtt/MQTTDefinitions.h | 15 ++ tools/AquaDebug/platformio.ini | 31 ++++ tools/AquaDebug/src/handler/OTA.cpp | 62 ++++++++ tools/AquaDebug/src/main.cpp | 119 +++++++++++++++ tools/AquaDebug/test/README | 11 ++ tools/AquaDebug/test/main.cpp | 40 +++++ 19 files changed, 636 insertions(+), 3 deletions(-) create mode 100644 tools/AquaDebug/.clang-format create mode 100644 tools/AquaDebug/.gitignore create mode 100644 tools/AquaDebug/.idea/.gitignore create mode 100644 tools/AquaDebug/.idea/codeStyles/Project.xml create mode 100644 tools/AquaDebug/.idea/codeStyles/codeStyleConfig.xml create mode 100644 tools/AquaDebug/.idea/misc.xml create mode 100644 tools/AquaDebug/.idea/vcs.xml create mode 100644 tools/AquaDebug/README.md create mode 100755 tools/AquaDebug/collect.py create mode 100644 tools/AquaDebug/include/config/Configuration.h create mode 100644 tools/AquaDebug/include/config/ExampleConfiguration.h create mode 100644 tools/AquaDebug/include/handler/OTA.h create mode 100644 tools/AquaDebug/include/mqtt/MQTTDefinitions.h create mode 100644 tools/AquaDebug/platformio.ini create mode 100644 tools/AquaDebug/src/handler/OTA.cpp create mode 100644 tools/AquaDebug/src/main.cpp create mode 100644 tools/AquaDebug/test/README create mode 100644 tools/AquaDebug/test/main.cpp diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md index fddfcf0..806b934 100644 --- a/TROUBLESHOOTING.md +++ b/TROUBLESHOOTING.md @@ -84,7 +84,7 @@ flowchart TD time. If this counter is rising, there might be connectivity issues or a different heatpump protocol using a different CRC mechanism. -- Both counter values `msgHandled` and `msgSent` shall be rising over time if the connection is good. If these values stay at `0` there are connectivity issues. +- The value `msgHandled` shall be rising over time if the connection is good. If this value stays at `0` there are most likely connectivity issues or the heat pump protocol is not (yet) supported. ### Q: AquaMQTT is connected to MQTT, but I don't see any values from the heatpump? @@ -108,7 +108,7 @@ It seems that depending on your heat-pump brand and model there are sometimes fo ### Q: Why do I need the HMI controller? Do I have to connect the HMI controller? In both of AquaMQTT current implemented OperationModes `LISTENER` and `MITM` it is expected to have an HMI controller -connected, since AquaMQTT is either just forwarding or altering the original messages emitted by the heat-pump +connected, since AquaMQTT is either just listening or forwarding original or modified messages emitted by the heat-pump controllers. Technically it would be feasible to build another OperationMode without the need for the original HMI controller, but @@ -146,4 +146,8 @@ There is a [python script](./tools) which subscribes all the debug topics and wr *The python script has to be modified to connect to your mqtt broker, with your mqtt broker credentials etc.* -Afterwards you can inspect changing values over time and identify attributes by making changes to your HMI controller. If you identifiy something new which is not documented within [PROTOCOL.md](./PROTOCOL.md) yet, please create an issue or even an PR. \ No newline at end of file +Afterwards you can inspect changing values over time and identify attributes by making changes to your HMI controller. If you identifiy something new which is not documented within [PROTOCOL.md](./PROTOCOL.md) yet, please create an issue or even an PR. + +### Q: I think my heat-pump uses an incompatible serial protocol? What can I do? + +If you already have the AquaMQTT Board installed and available, you can set it to LISTENER Mode and install [AquaDebug](./tools/AquaDebug/) to collect unmodified serial data traces from the heat-pump controller. If there are no other hardware and or connectivity related issues you should be able to identify the [heat-pump messages](./PROTOCOL.md) within the raw data. If the messages differ from the expected protocol, open up an github issue to discuss further. diff --git a/tools/AquaDebug/.clang-format b/tools/AquaDebug/.clang-format new file mode 100644 index 0000000..cb02385 --- /dev/null +++ b/tools/AquaDebug/.clang-format @@ -0,0 +1,137 @@ +# Configured for clang-format-9 +# If You want to test some setting, try https://zed0.co.uk/clang-format-configurator/ +# Integration helpers, see here: https://clang.llvm.org/docs/ClangFormat.html + +Language: Cpp +BasedOnStyle: Google +AccessModifierOffset: -4 +AllowAllConstructorInitializersOnNextLine: false +AllowAllArgumentsOnNextLine : false +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AlignConsecutiveMacros: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BreakBeforeBraces: Custom +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + AfterExternBlock: false + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true + AfterCaseLabel: true +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +BreakInheritanceList: BeforeComma +ColumnLimit: 119 +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 8 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH + - std::for_each +IncludeBlocks: Regroup +IncludeCategories: + + - Regex: '^<(gmock|gtest|Poco|rapidjson|eb)\/([A-Z0-9.\/-_])+' + Priority: 4 + + - Regex: '^<([A-Z0-9\/-_])+>' + Priority: 3 + + - Regex: '^<.*/.*\.hpp>' + Priority: 5 + + - Regex: '^<.*.h>' + Priority: 1 + + - Regex: '^<.*/.*\.h>' + Priority: 2 + + - Regex: '^".*/.*\.hpp"' + Priority: 6 + + - Regex: '^"([A-Z0-9.-_])+"' + Priority: 7 + +IncludeIsMainRegex: '(_test)?$' +IndentCaseLabels: true +IndentPPDirectives: AfterHash +IndentWidth: 4 +IndentWrappedFunctionNames: true +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +PointerAlignment: Left +RawStringFormats: + - Language: TextProto + BasedOnStyle: google + Delimiters: - pb +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never + +PenaltyBreakAssignment: 200 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 diff --git a/tools/AquaDebug/.gitignore b/tools/AquaDebug/.gitignore new file mode 100644 index 0000000..53ef685 --- /dev/null +++ b/tools/AquaDebug/.gitignore @@ -0,0 +1,2 @@ +.pio +include/config/CustomConfiguration.h \ No newline at end of file diff --git a/tools/AquaDebug/.idea/.gitignore b/tools/AquaDebug/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/tools/AquaDebug/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/tools/AquaDebug/.idea/codeStyles/Project.xml b/tools/AquaDebug/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..f603881 --- /dev/null +++ b/tools/AquaDebug/.idea/codeStyles/Project.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/tools/AquaDebug/.idea/codeStyles/codeStyleConfig.xml b/tools/AquaDebug/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/tools/AquaDebug/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/tools/AquaDebug/.idea/misc.xml b/tools/AquaDebug/.idea/misc.xml new file mode 100644 index 0000000..d858eb1 --- /dev/null +++ b/tools/AquaDebug/.idea/misc.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/tools/AquaDebug/.idea/vcs.xml b/tools/AquaDebug/.idea/vcs.xml new file mode 100644 index 0000000..64713b8 --- /dev/null +++ b/tools/AquaDebug/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/tools/AquaDebug/README.md b/tools/AquaDebug/README.md new file mode 100644 index 0000000..951ce1c --- /dev/null +++ b/tools/AquaDebug/README.md @@ -0,0 +1,39 @@ +# AquaDebug + +AquaDebug is a simple serial bus debugging application meant to be flashed on the AquaMQTT Board for troubleshooting the +heat-pumps serial protocol. + +- AquaDebug is sniffing the serial protocol without altering or interpreting any data +- AquaDebug expects the AquaMQTT Board to be configured as LISTENER +- AquaDebug reads the heat-pumps serial protocol and provides raw data to MQTT +- A python script running on any machine collects the data from MQTT and writes the data into files + +In case you suspect that your heat-pump is incompatible with the existing AquaMQTT implementation, due to a different +protocol, CRC or any other reason, you may try AquaDebug and provide a trace from your heat-pump communication as an +github issue. + +## Getting Started + +Refer to the [AquaMQTT README](./../../AquaMQTT/README.md) for installation and configuration instructions. + +## Debugging / Troubleshooting + +As soon as AquaDebug has been flashed, it will publish mqtt messages to `$prefix/aquadbg/debug` in case values have been +read from the Serial port. + +These data is collected by a little python script and stored on your machine. + +### Create the python environment + +``` +python3 -m venv venv +source venv/bin/activate +pip install paho-mqtt +``` + +### Run the python script + +``` +source venv/bin/activate +python3 collect.py +``` \ No newline at end of file diff --git a/tools/AquaDebug/collect.py b/tools/AquaDebug/collect.py new file mode 100755 index 0000000..90874d3 --- /dev/null +++ b/tools/AquaDebug/collect.py @@ -0,0 +1,44 @@ +import os +import time +import datetime +import paho.mqtt.client as mqtt + +last_payloads = {} + +def on_message(client, userdata, message): + topic = message.topic + payload = message.payload + + hex_file_name = topic.replace('/', '_') + '_hex.csv' + dec_file_name = topic.replace('/', '_') + '_dec.csv' + + hex_payload = payload.decode('utf-8') + + if topic in last_payloads and last_payloads[topic] == hex_payload: + return + + timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f') + + with open(hex_file_name, 'a') as hex_file: + hex_file.write(timestamp + ',' + hex_payload + '\n') + + dec_payload = ' '.join([str(int(payload[i:i+2], 16)) for i in range(0, len(payload), 2)]) + + with open(dec_file_name, 'a') as dec_file: + dec_file.write(timestamp + ',' + dec_payload + '\n') + + last_payloads[topic] = hex_payload + +client = mqtt.Client() +client.username_pw_set(username='your-broker-user', password='your-broker-pass') +client.connect('your-broker-addr', 1883) + +client.subscribe('your-prefix/aquadbg/debug') + +client.on_message = on_message + +client.loop_start() + +while True: + time.sleep(1) + diff --git a/tools/AquaDebug/include/config/Configuration.h b/tools/AquaDebug/include/config/Configuration.h new file mode 100644 index 0000000..79f7846 --- /dev/null +++ b/tools/AquaDebug/include/config/Configuration.h @@ -0,0 +1,44 @@ +#ifndef AQUAMQTT_CONFIGURATION_H +#define AQUAMQTT_CONFIGURATION_H + +/** + * Possibility to include your own configuration file (added to .gitignore) + */ +//#define CUSTOM_CONFIGURATION + +#ifdef CUSTOM_CONFIGURATION +# include "CustomConfiguration.h" +#else +# include "ExampleConfiguration.h" +#endif + +namespace aquamqtt +{ +namespace config +{ +/** + * Defines the network name of your esp32 device in your network + */ +constexpr char networkName[] = "aquamqtt"; + +/** + * Self explanatory internal settings: most probably you don't want to change them. + */ +constexpr uint8_t WATCHDOG_TIMEOUT_S = 60; +constexpr uint8_t MQTT_MAX_TOPIC_SIZE = 80; +constexpr uint8_t MQTT_MAX_PAYLOAD_SIZE = 255; + +/** + * Pin assignments for AquaMQTT Board Rev 1.0 + */ +constexpr uint8_t GPIO_MAIN_RX = 2; +constexpr uint8_t GPIO_MAIN_TX = 3; +constexpr uint8_t GPIO_HMI_RX = 4; +constexpr uint8_t GPIO_HMI_TX = 5; +constexpr uint8_t GPIO_SDA_RTC = A4; +constexpr uint8_t GPIO_SCL_RTC = A5; + +} // namespace config +} // namespace aquamqtt + +#endif // AQUAMQTT_CONFIGURATION_H diff --git a/tools/AquaDebug/include/config/ExampleConfiguration.h b/tools/AquaDebug/include/config/ExampleConfiguration.h new file mode 100644 index 0000000..3f4302f --- /dev/null +++ b/tools/AquaDebug/include/config/ExampleConfiguration.h @@ -0,0 +1,22 @@ +#ifndef AQUAMQTT_EXAMPLECONFIGURATION_H +#define AQUAMQTT_EXAMPLECONFIGURATION_H + +namespace aquamqtt +{ +namespace config +{ + +constexpr char ssid[] = "ExampleSSID"; +constexpr char psk[] = "ExamplePSK"; +constexpr char brokerAddr[] = "192.168.188.1"; +constexpr uint16_t brokerPort = 1883; +constexpr char brokerClientId[] = "aquamqtt"; +// leave blank if your broker does not require a username/password +constexpr char brokerUser[] = ""; +constexpr char brokerPassword[] = ""; +constexpr char mqttPrefix[] = ""; + +} // namespace config +} // namespace aquamqtt + +#endif // AQUAMQTT_EXAMPLECONFIGURATION_H diff --git a/tools/AquaDebug/include/handler/OTA.h b/tools/AquaDebug/include/handler/OTA.h new file mode 100644 index 0000000..6307a98 --- /dev/null +++ b/tools/AquaDebug/include/handler/OTA.h @@ -0,0 +1,19 @@ +#ifndef AQUAMQTT_OTA_H +#define AQUAMQTT_OTA_H + +namespace aquamqtt +{ +class OTAHandler +{ +public: + OTAHandler() = default; + + virtual ~OTAHandler() = default; + + void setup(); + + void loop(); +}; +} // namespace aquamqtt + +#endif // AQUAMQTT_OTA_H diff --git a/tools/AquaDebug/include/mqtt/MQTTDefinitions.h b/tools/AquaDebug/include/mqtt/MQTTDefinitions.h new file mode 100644 index 0000000..d09d79c --- /dev/null +++ b/tools/AquaDebug/include/mqtt/MQTTDefinitions.h @@ -0,0 +1,15 @@ +#ifndef AQUAMQTT_MQTTDEFINITIONS_H +#define AQUAMQTT_MQTTDEFINITIONS_H + +namespace aquamqtt +{ +namespace mqtt +{ + +constexpr char BASE_TOPIC[] = { "aquadbg/" }; +constexpr char DEBUG[] = { "debug" }; + +} // namespace mqtt +} // namespace aquamqtt + +#endif // AQUAMQTT_MQTTDEFINITIONS_H diff --git a/tools/AquaDebug/platformio.ini b/tools/AquaDebug/platformio.ini new file mode 100644 index 0000000..4e5914c --- /dev/null +++ b/tools/AquaDebug/platformio.ini @@ -0,0 +1,31 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env] +test_framework = googletest + +[env:native] +platform = native +build_src_filter = src/** +lib_deps = + googletest + +[env:arduino_nano_esp32] +platform = espressif32 +board = arduino_nano_esp32 +framework = arduino +test_framework = googletest +build_flags = -std=c++11 +# uncomment the below lines to use over the air update +# upload_protocol = espota +# upload_port = 192.168.188.62 +lib_deps = + locoduino/RingBuffer + 256dpi/MQTT diff --git a/tools/AquaDebug/src/handler/OTA.cpp b/tools/AquaDebug/src/handler/OTA.cpp new file mode 100644 index 0000000..7d71e88 --- /dev/null +++ b/tools/AquaDebug/src/handler/OTA.cpp @@ -0,0 +1,62 @@ +#include "handler/OTA.h" + +#include + +#include "config/Configuration.h" + +namespace aquamqtt +{ + +void OTAHandler::setup() // NOLINT(*-convert-member-functions-to-static) +{ + // Port defaults to 3232 + // ArduinoOTA.setPort(3232); + + // Hostname defaults to esp3232-[MAC] + ArduinoOTA.setHostname(config::networkName); + + // No authentication by default + // ArduinoOTA.setPassword("admin"); + + // Password can be set with it's md5 value as well + // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3 + // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3"); + + ArduinoOTA + .onStart([]() { + String type; + if (ArduinoOTA.getCommand() == U_FLASH) + type = "sketch"; + else // U_SPIFFS + type = "filesystem"; + + // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() + Serial.println("Start updating " + type); + }) + .onEnd([]() { Serial.println("\nEnd"); }) + .onProgress([](unsigned int progress, unsigned int total) { + Serial.printf("Progress: %u%%\r", (progress / (total / 100))); + }) + .onError([](ota_error_t error) { + Serial.printf("Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) + Serial.println("Auth Failed"); + else if (error == OTA_BEGIN_ERROR) + Serial.println("Begin Failed"); + else if (error == OTA_CONNECT_ERROR) + Serial.println("Connect Failed"); + else if (error == OTA_RECEIVE_ERROR) + Serial.println("Receive Failed"); + else if (error == OTA_END_ERROR) + Serial.println("End Failed"); + }); + + ArduinoOTA.begin(); +} + +void OTAHandler::loop() // NOLINT(*-convert-member-functions-to-static) +{ + ArduinoOTA.handle(); +} + +} // namespace aquamqtt diff --git a/tools/AquaDebug/src/main.cpp b/tools/AquaDebug/src/main.cpp new file mode 100644 index 0000000..0044a0f --- /dev/null +++ b/tools/AquaDebug/src/main.cpp @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include + +#include "config/Configuration.h" +#include "handler/OTA.h" +#include "mqtt/MQTTDefinitions.h" + +using namespace aquamqtt; +using namespace aquamqtt::config; +using namespace aquamqtt::mqtt; + +constexpr uint16_t BUFFER_SIZE = 40; + +WiFiClient mWiFiClient; +MQTTClient mMQTTClient(256); +RingBuf mBuffer; +OTAHandler otaHandler; +uint8_t mTopicBuffer[config::MQTT_MAX_TOPIC_SIZE]; +uint8_t mPayloadBuffer[MQTT_MAX_PAYLOAD_SIZE]; +uint8_t mTempBuffer[BUFFER_SIZE]; + +void toHexStr(uint8_t* data, uint8_t data_len, char* buffer) +{ + const size_t num_bytes = data_len / sizeof(uint8_t); + // char hex_str[num_bytes * 2 + 1]; + for (size_t i = 0; i < num_bytes; i++) + { + sprintf(&buffer[i * 2], "%02X", data[i]); + } + buffer[num_bytes * 2] = '\0'; +} + +void wifiCallback(WiFiEvent_t event) +{ + switch (event) + { + case WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_CONNECTED: + Serial.println(F("ARDUINO_EVENT_WIFI_STA_CONNECTED")); + break; + case WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED: + Serial.println(F("ARDUINO_EVENT_WIFI_STA_DISCONNECTED")); + WiFi.setAutoReconnect(true); + break; + default: + break; + } +} + +void loop() +{ + // watchdog + esp_task_wdt_reset(); + + // handle over-the-air module in main thread + otaHandler.loop(); + + // connect mqtt if not connected + if (!mMQTTClient.connected()) + { + mMQTTClient.connect( + aquamqtt::config::brokerClientId, + strlen(aquamqtt::config::brokerUser) == 0 ? nullptr : aquamqtt::config::brokerUser, + strlen(aquamqtt::config::brokerPassword) == 0 ? nullptr : aquamqtt::config::brokerPassword); + } + else + { + mMQTTClient.loop(); + } + + // read serial into buffer + while (Serial2.available()) + { + // push new element to the back + mBuffer.push(Serial2.read()); + + // if buffer is full, we emit everything to mqtt and clear the buffer + if (mBuffer.isFull()) + { + for (int i = 0; i < BUFFER_SIZE; i++) + { + int retVal; + mBuffer.pop(retVal); + mTempBuffer[i] = retVal; + } + sprintf(reinterpret_cast(mTopicBuffer), "%s%s%s", config::mqttPrefix, BASE_TOPIC, DEBUG); + toHexStr(mTempBuffer, BUFFER_SIZE, reinterpret_cast(mPayloadBuffer)); + mMQTTClient.publish(reinterpret_cast(mTopicBuffer), reinterpret_cast(mPayloadBuffer)); + } + } +} + +void setup() +{ + // limited serial output for debuggability + Serial.begin(9600); + Serial.println("REBOOT"); + + // initialize watchdog + esp_task_wdt_init(WATCHDOG_TIMEOUT_S, true); + esp_task_wdt_add(nullptr); + + // connect to Wi-Fi + WiFiClass::mode(WIFI_STA); + WiFi.onEvent(wifiCallback); + WiFi.begin(aquamqtt::config::ssid, aquamqtt::config::psk); + + // setup ota module + otaHandler.setup(); + + // setup mqtt client + mMQTTClient.begin(aquamqtt::config::brokerAddr, aquamqtt::config::brokerPort, mWiFiClient); + + // setup serial port + Serial2.begin(9550, SERIAL_8N2, aquamqtt::config::GPIO_MAIN_RX, aquamqtt::config::GPIO_MAIN_TX); +} \ No newline at end of file diff --git a/tools/AquaDebug/test/README b/tools/AquaDebug/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/tools/AquaDebug/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html diff --git a/tools/AquaDebug/test/main.cpp b/tools/AquaDebug/test/main.cpp new file mode 100644 index 0000000..942f3dd --- /dev/null +++ b/tools/AquaDebug/test/main.cpp @@ -0,0 +1,40 @@ +#include + +#if defined(ARDUINO) +#include + +void setup() +{ + // should be the same value as for the `test_speed` option in "platformio.ini" + // default value is test_speed=115200 + Serial.begin(115200); + + ::testing::InitGoogleTest(); + // if you plan to use GMock, replace the line above with + // ::testing::InitGoogleMock(); +} + +void loop() +{ + // Run tests + if (RUN_ALL_TESTS()) + ; + + // sleep for 1 sec + delay(1000); +} + +#else +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + // if you plan to use GMock, replace the line above with + // ::testing::InitGoogleMock(&argc, argv); + + if (RUN_ALL_TESTS()) + ; + + // Always return zero-code and allow PlatformIO to parse results + return 0; +} +#endif \ No newline at end of file