├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── compile-arduino.yml │ ├── compile-platformio.yml │ └── spell-check.yml ├── .gitignore ├── LICENSE ├── README.md ├── SolarTracerBlynk ├── SolarTracerBlynk.ino ├── config.h └── src │ ├── board │ ├── esp32_config.h │ └── esp8266_config.h │ ├── core │ ├── BaseSync.cpp │ ├── BaseSync.h │ ├── Controller.cpp │ ├── Controller.h │ ├── Environment.cpp │ ├── Environment.h │ ├── Text.h │ ├── Util.cpp │ ├── Util.h │ ├── VariableDefiner.cpp │ ├── VariableDefiner.h │ ├── datetime.h │ ├── debug.cpp │ └── debug.h │ ├── feature │ ├── BlynkSync.cpp │ ├── BlynkSync.h │ ├── MqttHASync.cpp │ ├── MqttHASync.h │ ├── MqttSync.cpp │ ├── MqttSync.h │ ├── arduino_ota.h │ └── wifi_manager.h │ ├── incl │ ├── communication_protocol_all.h │ ├── config_persistence.h │ ├── include.h │ ├── include_all_blynk_vpin.h │ ├── include_all_core.h │ ├── include_all_feature.h │ ├── include_all_lib.h │ ├── include_all_mqtt_topic.h │ ├── solartracer_all.h │ └── status_all.h │ └── solartracer │ ├── SolarTracer.cpp │ ├── SolarTracer.h │ ├── dummy │ └── DummySolarTracer.h │ ├── epever │ ├── EPEVERSolarTracer.cpp │ ├── EPEVERSolarTracer.h │ ├── EPEVER_modbus_address.h │ └── epever_config.h │ ├── incl │ └── solar_config.h │ └── overwrite │ ├── LoadCurrentOverWrite.cpp │ └── LoadCurrentOverwrite.h ├── docs ├── 1733_modbus_protocol.pdf ├── Esp32_max485_epever_rj45.md ├── Esp8266_max485_epever_rj45.md ├── Sw_getting_started.md ├── esp32.md ├── esp8266.md ├── sw_getting_started_blynk_iot.md ├── sw_getting_started_blynk_legacy.md ├── sw_getting_started_ha.md └── sw_getting_started_mqtt.md ├── images ├── blynk-app-qr-code.png ├── blynk-app-qr-code_v3.png ├── blynk-app-qr-code_v3_blynkcloud.png ├── epever_rj45_specs.png ├── esp32_d1_mini_pins.png ├── esp32_wroom_38_pin.jpg ├── esp8266_bin_flash.png ├── esp8266_hw_serial.png ├── esp8266_sw_serial.png ├── esp_tool_bin_flash_10000.png ├── esp_tool_bin_flash_new.png ├── esp_tool_board_select.png ├── eth_t568b.png ├── max485_module.jpg ├── mppt-triton.png ├── mppt-xtra.png ├── nodemcu_pins.png ├── schematic.png ├── screenshot-blynk.png ├── screenshot-blynk_v3_battery.png ├── screenshot-blynk_v3_pv.png ├── screenshot-blynk_v3_realtime.png ├── screenshot-blynk_v3_settings.png ├── tracer-a.png ├── tracer-b.png ├── wifi_manager.png ├── wifi_manager_config.png ├── wifi_manager_home.png ├── wifi_manager_mqtt_settings.png ├── wifi_manager_update.png └── wifi_manager_update_upload.png ├── platformio.ini └── script ├── binDeploy.cmd ├── binTest.cmd └── esp32_binary_merger ├── LICENSE └── merge_bin_esp.py /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: bettapro 2 | liberapay: bettapro 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: Bettapro 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/compile-arduino.yml: -------------------------------------------------------------------------------- 1 | name: Compile Arduino 2 | 3 | on: 4 | push: 5 | paths: 6 | - ".github/workflows/compile-arduino.yml" 7 | - "SolarTracerBlynk/**" 8 | pull_request: 9 | paths: 10 | - ".github/workflows/compile-arduino.yml" 11 | - "SolarTracerBlynk/**" 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | # This workflow contains a single job called "build" 19 | build: 20 | # The type of runner that the job will run on 21 | runs-on: ubuntu-latest 22 | 23 | env: 24 | # libraries to install for all boards 25 | shared_libraries: | 26 | - name: ArduinoOTA 27 | - name : WiFi 28 | - name: Blynk 29 | version: 1.1.0 30 | - name: WiFiManager 31 | - name: ArduinoJson 32 | - source-url : https://github.com/Bettapro/ModbusMaster.git 33 | - name: PubSubClient 34 | - source-url : https://github.com/Bettapro/SimpleTimer.git 35 | - source-url : https://github.com/dawidchyrzynski/arduino-home-assistant.git 36 | version : 2.1.0 37 | - source-url : https://github.com/Bettapro/LinearSensHallCurrent.git 38 | - source-url : https://github.com/RobTillaart/ADS1X15.git 39 | - source-url : https://github.com/khoih-prog/ESP_DoubleResetDetector.git 40 | - source-url : https://github.com/plerup/espsoftwareserial.git 41 | version : 8.0.3 42 | # sketch paths to compile (recursive) for all boards 43 | sketch_paths: | 44 | - SolarTracerBlynk 45 | 46 | strategy: 47 | matrix: 48 | board: 49 | - fqbn: esp8266:esp8266:arduino-esp8266 50 | type: esp8266 51 | - fqbn: esp32:esp32:esp32 52 | type: esp32 53 | 54 | include: 55 | # ESP8266 boards 56 | - board: 57 | type: esp8266 58 | platforms: | 59 | - name: esp8266:esp8266@3.0.2 60 | source-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json 61 | libraries: 62 | # ESP32 boards 63 | - board: 64 | type: esp32 65 | platforms: | 66 | - name: esp32:esp32 67 | source-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json 68 | libraries: 69 | 70 | steps: 71 | - name: Checkout 72 | uses: actions/checkout@v2 73 | - name: Compile Sketches 74 | uses: arduino/compile-sketches@v1 75 | with: 76 | github-token: ${{ secrets.GITHUB_TOKEN }} 77 | platforms: ${{ matrix.platforms }} 78 | fqbn: ${{ matrix.board.fqbn }} 79 | sketch-paths: | 80 | ${{ env.sketch_paths }} 81 | libraries: | 82 | ${{ env.shared_libraries }} 83 | ${{ matrix.libraries }} 84 | enable-deltas-report: "true" 85 | sketches-report-path: sketches-reports 86 | cli-compile-flags: | 87 | - --warnings="all" 88 | # - --build-property 89 | # - compiler.cpp.extra_flag="-Wno-unused-function" 90 | - name: Report Arduino Sketch Size Deltas 91 | uses: arduino/report-size-deltas@v1.0.0 92 | with: 93 | # When run from scheduled workflow, name of the workflow artifact that contains sketches reports. When run from a pull request triggered workflow, path to the folder containing sketches reports. 94 | sketches-reports-source: sketches-reports 95 | # GitHub access token used to comment the memory usage comparison results to the PR thread 96 | github-token: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/compile-platformio.yml: -------------------------------------------------------------------------------- 1 | name: Compile Platformio 2 | 3 | on: 4 | push: 5 | paths: 6 | - ".github/workflows/compile-arduino.yml" 7 | - "SolarTracerBlynk/**" 8 | pull_request: 9 | paths: 10 | - ".github/workflows/compile-arduino.yml" 11 | - "SolarTracerBlynk/**" 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | # This workflow contains a single job called "build" 19 | test_builds: 20 | runs-on: ubuntu-latest 21 | 22 | strategy: 23 | matrix: 24 | test-platform: 25 | # Base Environments 26 | - esp32dev 27 | - esp8266 28 | 29 | steps: 30 | - name: Check out the PR 31 | uses: actions/checkout@v2 32 | 33 | - name: Cache pip 34 | uses: actions/cache@v2 35 | with: 36 | path: ~/.cache/pip 37 | key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} 38 | restore-keys: | 39 | ${{ runner.os }}-pip- 40 | 41 | - name: Cache PlatformIO 42 | uses: actions/cache@v2 43 | with: 44 | path: ~/.platformio 45 | key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }} 46 | 47 | - name: Select Python 3.7 48 | uses: actions/setup-python@v2 49 | with: 50 | python-version: '3.7' # Version range or exact version of a Python version to use, using semvers version range syntax. 51 | architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified 52 | 53 | - name: Install PlatformIO 54 | run: | 55 | pip install -U https://github.com/platformio/platformio-core/archive/develop.zip 56 | platformio update 57 | 58 | - name: Run ${{ matrix.test-platform }} Tests 59 | run: | 60 | pio run -e ${{ matrix.test-platform }} 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /.github/workflows/spell-check.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Spell Check 3 | 4 | on: 5 | push: 6 | pull_request: 7 | 8 | # Allows you to run this workflow manually from the Actions tab 9 | workflow_dispatch: 10 | 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v2 18 | - name: Spell check 19 | uses: codespell-project/actions-codespell@master 20 | with: 21 | skip: ./docs/1733_modbus_protocol.pdf 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Platformio 2 | .pio 3 | 4 | # Visual Studio Code 5 | .vscode 6 | *.code-workspace 7 | 8 | #build folder 9 | binFiles 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Solar-tracer-Blynk-V3 3 | 4 | [![Compile Arduino](https://github.com/Bettapro/Solar-Tracer-Blynk-V3/actions/workflows/compile-arduino.yml/badge.svg)](https://github.com/Bettapro/Solar-Tracer-Blynk-V3/actions/workflows/compile-arduino.yml) 5 | [![Compile Platformio](https://github.com/Bettapro/Solar-Tracer-Blynk-V3/actions/workflows/compile-platformio.yml/badge.svg)](https://github.com/Bettapro/Solar-Tracer-Blynk-V3/actions/workflows/compile-platformio.yml) 6 | [![Spell Check](https://github.com/Bettapro/Solar-Tracer-Blynk-V3/actions/workflows/spell-check.yml/badge.svg)](https://github.com/Bettapro/Solar-Tracer-Blynk-V3/actions/workflows/spell-check.yml) 7 | 8 | 9 | ### An Arduino project to connect one MPPT Solar Controllers to an `ESP8266/ESP32` and monitor it! 10 | 11 | You can take a look to the previous version of this software: 12 | * *v1* [Tracer-RS485-Modbus-Blynk](https://github.com/jaminNZx/Tracer-RS485-Modbus-Blynk) 13 | * *v2* [Tracer-RS485-Modbus-Blynk-V2](https://github.com/tekk/Tracer-RS485-Modbus-Blynk-V2) 14 | 15 | What you got with v3: 16 | 1. **lots of data** from you solar controller (temps, charging/discharging/battery status, stats ... and more) 17 | 2. wide range of **customization** using a single file (*config.h*) 18 | 3. automatic **time sync** between the ESP and the controller on each boot, using NTP time 19 | 4. **platformio** support 20 | 5. **ESP32** support 21 | 6. **Configuration over wifi**, no needs to compile the code (if you don't want to) 22 | 7. ready for future expansion (more solar charge controllers with different communication protocol/channel) 23 | 24 | Feel free to make pull requests if you wish to help improving. 25 | There is also a support forum on the Blynk community forums: http://community.blynk.cc/t/epsolar-tracer-2210a-charge-controller-blynk-epic-solar-monitor/10596 26 | 27 | You are welcome for suggestions, bugreports, and of course any further improvements of this code. 28 | 29 | ## Solar Controller Supported 30 | 31 | ![Triton](images/mppt-triton.png) 32 | ![Xtra](images/mppt-xtra.png) 33 | ![Tracer-AN](images/tracer-a.png) 34 | ![Tracer-BN](images/tracer-b.png) 35 | 36 | ## Tutorial 37 | Supported board: 38 | - [ESP8266](docs/esp8266.md) 39 | - [ESP32](docs/esp32.md) 40 | 41 | Available sync. options: 42 | - [Blynk legacy](docs/sw_getting_started_blynk_legacy.md) 43 | - [Blynk IOT](docs/sw_getting_started_blynk_iot.md) 44 | - [Home assistant-MQTT](docs/sw_getting_started_ha.md) 45 | - [MQTT](docs/sw_getting_started_mqtt.md) 46 | 47 | 48 | Some examples: 49 | - [ESP8266 + MAX485 + EPEVER Solar Tracer](docs/Esp8266_max485_epever_rj45.md) 50 | - [ESP32 + MAX485 + EPEVER Solar Tracer](docs/Esp32_max485_epever_rj45.md) 51 | 52 | ## Sample screenshot 53 | 54 | ![Realtime data BLYNK LEGACY](images/screenshot-blynk_v3_realtime.png) 55 | ![PV data screen BLYNK LEGACY](images/screenshot-blynk_v3_pv.png) 56 | 57 | ## Credits 58 | 59 | - `@jaminNZx:` 60 | - Thanks to subtafuge on [Reddit](https://www.reddit.com/r/esp8266/comments/59dt00/using_esp8266_to_connect_rs485_modbus_protocol/) for lending me his working Tracer RS485 code! 61 | 62 | - `@tekk:` 63 | - Feel free to contact me about my code changes in this version 64 | - Thanks to [@jaminNZx](https://github.com/jaminNZx) for the original code. Big up! 65 | 66 | - `@bettapro:` 67 | - Thanks to [@tekk](https://github.com/tekk) for his work. Big up! 68 | - Feel free to contact me about my code changes in this version 69 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/board/esp32_config.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifdef ESP32 25 | 26 | #ifndef BOARD_DEBUG_SERIAL_STREAM 27 | #define BOARD_DEBUG_SERIAL_STREAM Serial 28 | #endif 29 | 30 | #ifndef BOARD_DEBUG_SERIAL_STREAM_BAUDRATE 31 | #define BOARD_DEBUG_SERIAL_STREAM_BAUDRATE 115200 32 | #endif 33 | 34 | #if defined USE_PIN_AP_CONFIGURATION_TRIGGER and ! defined(PIN_AP_TRIGGER_PIN) 35 | #define PIN_AP_TRIGGER_PIN 19 36 | #endif 37 | 38 | #if defined(USE_SERIAL_STREAM) && !defined(BOARD_ST_SERIAL_STREAM) 39 | #define BOARD_ST_SERIAL_STREAM Serial2 40 | #endif 41 | 42 | #if defined(USE_SERIAL_STREAM) && !defined(BOARD_ST_SERIAL_PRETRANSMIT_WAIT) 43 | #define BOARD_ST_SERIAL_PRETRANSMIT_WAIT 0 44 | #endif 45 | 46 | #if defined(USE_SERIAL_MAX485) && !defined(MAX485_DE) 47 | #define MAX485_DE 13 48 | #endif 49 | 50 | #if defined(USE_SERIAL_MAX485) && !defined(MAX485_RE_NEG) 51 | #define MAX485_RE_NEG 13 52 | #endif 53 | 54 | #if defined(USE_WIFI_AP_CONFIGURATION) && defined(USE_HALL_AP_CONFIGURATION_TRIGGER) 55 | #if !defined(HALL_AP_CONFIGURATION_BASE_VALUE) 56 | #define HALL_AP_CONFIGURATION_BASE_VALUE 75 57 | #endif 58 | #if !defined(HALL_AP_CONFIGURATION_THR_VALUE) 59 | #define HALL_AP_CONFIGURATION_THR_VALUE 30 60 | #endif 61 | #endif 62 | 63 | #define WIFI_STATION_MODE_DISCONNECTED WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED 64 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/board/esp8266_config.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifdef ESP8266 25 | 26 | #ifndef BOARD_DEBUG_SERIAL_STREAM 27 | #define BOARD_DEBUG_SERIAL_STREAM Serial 28 | #endif 29 | 30 | #ifndef BOARD_DEBUG_SERIAL_STREAM_BAUDRATE 31 | #define BOARD_DEBUG_SERIAL_STREAM_BAUDRATE 115200 32 | #endif 33 | 34 | #if defined USE_PIN_AP_CONFIGURATION_TRIGGER and ! defined(PIN_AP_TRIGGER_PIN) 35 | #define PIN_AP_TRIGGER_PIN 16 36 | #endif 37 | 38 | #ifdef USE_SOFTWARE_SERIAL 39 | #ifndef BOARD_ST_SERIAL_PIN_MAPPING_TX 40 | #define BOARD_ST_SERIAL_PIN_MAPPING_TX 4 41 | #endif 42 | #ifndef BOARD_ST_SERIAL_PIN_MAPPING_RX 43 | #define BOARD_ST_SERIAL_PIN_MAPPING_RX 2 44 | #endif 45 | #else 46 | #define BOARD_ST_SERIAL_DECLARATION 47 | #endif 48 | 49 | 50 | #if defined(USE_SERIAL_STREAM) && !defined(BOARD_ST_SERIAL_STREAM) && !defined(USE_SOFTWARE_SERIAL) 51 | #define BOARD_ST_SERIAL_STREAM Serial 52 | #endif 53 | 54 | #if defined(USE_SERIAL_STREAM) && !defined(BOARD_ST_SERIAL_PRETRANSMIT_WAIT) 55 | #define BOARD_ST_SERIAL_PRETRANSMIT_WAIT 10 56 | #endif 57 | 58 | #if defined(USE_SERIAL_MAX485) && !defined(MAX485_DE) 59 | #define MAX485_DE 5 60 | #endif 61 | 62 | #if defined(USE_SERIAL_MAX485) && !defined(MAX485_RE_NEG) 63 | #define MAX485_RE_NEG 5 64 | #endif 65 | 66 | 67 | #define WIFI_STATION_MODE_DISCONNECTED WiFiEvent_t::WIFI_EVENT_STAMODE_DISCONNECTED 68 | 69 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/BaseSync.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #include "BaseSync.h" 23 | 24 | #include "../core/Controller.h" 25 | #include "../core/VariableDefiner.h" 26 | #include "../core/debug.h" 27 | 28 | #define VALUE_CACHES_UNTIL_COUNT 100; 29 | 30 | BaseSync::BaseSync() { 31 | this->renewValuesCount = new uint8_t[Variable::VARIABLES_COUNT](); 32 | this->lastValuesCache = new void *[Variable::VARIABLES_COUNT](); 33 | 34 | uint8_t varSize; 35 | for (uint8_t index = 0; index < Variable::VARIABLES_COUNT; index++) { 36 | this->renewValuesCount[index] = 0; 37 | varSize = VariableDefiner::getInstance().getVariableSize((Variable)index); 38 | if (varSize > 0) { 39 | this->lastValuesCache[index] = malloc(varSize); 40 | memset(this->lastValuesCache[index], 0, varSize); 41 | } 42 | } 43 | } 44 | 45 | void BaseSync::applyUpdateToVariable(Variable variable, const void *value, bool silent) { 46 | SolarTracer *solarT = Controller::getInstance().getSolarController(); 47 | const VariableDefinition *def = VariableDefiner::getInstance().getDefinition(variable); 48 | if (def != nullptr) { 49 | if (!silent) { 50 | debugPrint("WRITE REQUEST "); 51 | switch (def->datatype) { 52 | case VariableDatatype::DT_FLOAT: 53 | debugPrintf(false, "\"%s\" to %.4f ", def->text, *(const float *)value); 54 | break; 55 | case VariableDatatype::DT_BOOL: 56 | debugPrintf(false, "\"%s\" to %i ", def->text, *(const bool *)value); 57 | break; 58 | case VariableDatatype::DT_STRING: 59 | debugPrintf(false, "\"%s\" to \"%s\" ", def->text, (const char *)value); 60 | break; 61 | } 62 | } 63 | bool writeDone = solarT->writeValue(variable, value); 64 | if (!silent) { 65 | writeDone ? debugPrintln(Text::ok) : debugPrintf(true, Text::errorWithCode, solarT->getLastControllerCommunicationStatus()); 66 | } 67 | } 68 | } 69 | 70 | uint8_t BaseSync::sendUpdateAllBySource(VariableSource allowedSource, bool silent) { 71 | SolarTracer *solarT = Controller::getInstance().getSolarController(); 72 | uint8_t varNotReady = 0; 73 | const VariableDefinition *def; 74 | 75 | for (uint8_t index = 0; index < Variable::VARIABLES_COUNT; index++) { 76 | def = VariableDefiner::getInstance().getDefinition((Variable)index); 77 | if (def->source == allowedSource && this->isVariableAllowed(def) && (solarT->isVariableEnabled(def->variable) || solarT->isVariableOverWritten(def->variable))) { 78 | if (!solarT->isVariableReadReady(def->variable) || !this->syncVariable(def, solarT->getValue(def->variable))) { 79 | #ifdef USE_DEBUG_SERIAL_VERBOSE_SYNC_ERROR_VARIABLE 80 | debugPrintf(true, Text::syncErrorWithVariable, def->text); 81 | #endif 82 | varNotReady++; 83 | } 84 | } 85 | } 86 | 87 | if (!silent && varNotReady > 0) { 88 | debugPrintf(true, Text::syncErrorWithCountAndType, varNotReady, allowedSource == VariableSource::SR_STATS ? "ST" : "RT"); 89 | } 90 | Controller::getInstance().setErrorFlag(allowedSource == VariableSource::SR_STATS ? STATUS_ERR_SOLAR_TRACER_NO_SYNC_ST : STATUS_ERR_SOLAR_TRACER_NO_SYNC_RT, varNotReady > 0); 91 | 92 | return varNotReady; 93 | } 94 | 95 | bool BaseSync::syncVariable(const VariableDefinition *def, const void *value) { 96 | uint8_t *cachedUntil = &(this->renewValuesCount[def->variable]); 97 | if (this->isVariableAllowed(def)) { 98 | if (!( 99 | this->renewValueCount == 1 || (*cachedUntil) <= 0 // sync always enabled? 100 | || !VariableDefiner::getInstance().isValueEqual(def->variable, value, this->lastValuesCache[def->variable]) // value has changed? 101 | || (this->renewValueCount > 1 && ((*cachedUntil)--) <= 0) // renew required? 102 | ) // -> should sync evaluation? 103 | || this->sendUpdateToVariable(def, value)) { 104 | memcpy(this->lastValuesCache[def->variable], value, VariableDefiner::getInstance().getVariableSize(def->variable)); 105 | if (this->renewValueCount > 1 || (*cachedUntil) <= 0) { 106 | (*cachedUntil) = this->renewValueCount + 1; 107 | } 108 | return true; 109 | } 110 | } 111 | return false; 112 | } -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/BaseSync.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef BASE_SYNC_H 25 | #define BASE_SYNC_H 26 | 27 | #include "../core/VariableDefiner.h" 28 | 29 | #define BASE_SYNC_RENEW_VALUE_COUNT 20; 30 | 31 | class BaseSync { 32 | public: 33 | BaseSync(); 34 | virtual void setup() = 0; 35 | virtual void connect(bool blocking = true) = 0; 36 | virtual void loop() = 0; 37 | /** 38 | * @brief Send the update to remote server 39 | * 40 | * @param def variable definition 41 | * @param value value 42 | * @return true if the update has been sent with success, false otherwise 43 | */ 44 | virtual bool sendUpdateToVariable(const VariableDefinition *def, const void *value) = 0; 45 | virtual bool isVariableAllowed(const VariableDefinition *def) = 0; 46 | void applyUpdateToVariable(Variable variable, const void *value, bool silent = true); 47 | 48 | bool syncVariable(const VariableDefinition *def, const void *value); 49 | 50 | uint8_t sendUpdateAllBySource(VariableSource allowedSource, bool silent = true); 51 | 52 | protected: 53 | /** 54 | * 0 sync on change only 55 | * 1 sync always 56 | * .. use renew count 57 | */ 58 | uint8_t renewValueCount = BASE_SYNC_RENEW_VALUE_COUNT; 59 | 60 | private: 61 | void **lastValuesCache; 62 | 63 | uint8_t *renewValuesCount; 64 | }; 65 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/Controller.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #include "Controller.h" 23 | 24 | bool Controller::getErrorFlag(const uint32_t status) { 25 | return (this->internalStatus & status) > 0; 26 | } 27 | 28 | void Controller::setErrorFlag(const uint32_t status, bool error) { 29 | if (this->getErrorFlag(status) != error) { 30 | uint32_t tStatus = this->internalStatus + (error ? 1 : -1) * status; 31 | #ifdef USE_STATUS_LED 32 | notifyStatusLed(tStatus); 33 | #endif 34 | this->internalStatus = tStatus; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/Controller.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef CONTROLLER_H 25 | #define CONTROLLER_H 26 | 27 | #include "../incl/include_all_lib.h" 28 | #include "../solartracer/SolarTracer.h" 29 | 30 | class Controller { 31 | public: 32 | static Controller &getInstance() { 33 | static Controller instance; 34 | return instance; 35 | } 36 | 37 | void setup(SolarTracer *tracer, SimpleTimer *timer) { 38 | this->mainTimer = timer; 39 | this->thisController = tracer; 40 | } 41 | 42 | void loop() { 43 | this->mainTimer->run(); 44 | } 45 | 46 | bool getErrorFlag(uint32_t status); 47 | 48 | void setErrorFlag(uint32_t status, bool error); 49 | 50 | inline uint32_t getStatus(); 51 | 52 | inline SolarTracer *getSolarController(); 53 | 54 | inline SimpleTimer *getMainTimer(); 55 | 56 | private: 57 | SimpleTimer *mainTimer; 58 | SolarTracer *thisController; 59 | uint32_t internalStatus = 0; 60 | }; 61 | 62 | uint32_t Controller::getStatus() { 63 | return this->internalStatus; 64 | } 65 | 66 | SolarTracer *Controller::getSolarController() { 67 | return this->thisController; 68 | } 69 | 70 | SimpleTimer *Controller::getMainTimer() { 71 | return this->mainTimer; 72 | } 73 | 74 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/Environment.cpp: -------------------------------------------------------------------------------- 1 | #include "Environment.h" 2 | 3 | struct EnvironrmentData Environment::envData; 4 | 5 | void Environment::loadEnvData() { 6 | envData.serialDebug = true; 7 | // default from config.h 8 | strcpy(envData.wifiSSID, WIFI_SSID); 9 | strcpy(envData.wifiPassword, WIFI_PASS); 10 | 11 | strcpy(envData.wifiIp, WIFI_IP_ADDRESS); 12 | strcpy(envData.wifiGateway, WIFI_GATEWAY); 13 | strcpy(envData.wifiSubnet, WIFI_SUBNET); 14 | strcpy(envData.wifiDns1, WIFI_DNS1); 15 | strcpy(envData.wifiDns2, WIFI_DNS2); 16 | 17 | #ifdef USE_WIFI_AP_CONFIGURATION 18 | strcpy(envData.wmApSSID, WIFI_AP_CONFIGURATION_HOSTNAME); 19 | strcpy(envData.wmApPassword, WIFI_AP_CONFIGURATION_PASSWORD); 20 | #endif 21 | 22 | #ifdef USE_BLYNK 23 | #ifndef USE_BLYNK_2 24 | #ifdef USE_BLYNK_LOCAL_SERVER 25 | strcpy(envData.blynkServerHostname, BLYNK_SERVER); 26 | envData.blynkServerPort = BLYNK_PORT; 27 | #else 28 | strcpy(envData.blynkServerHostname, ""); 29 | envData.blynkServerPort = 0; 30 | #endif 31 | #endif 32 | #if defined USE_BLYNK 33 | strcpy(envData.blynkAuth, BLYNK_AUTH); 34 | #endif 35 | #endif 36 | #ifdef USE_MQTT 37 | strcpy(envData.mqttServerHostname, MQTT_SERVER); 38 | strcpy(envData.mqttUsername, MQTT_USERNAME); 39 | strcpy(envData.mqttPassword, MQTT_PASSWORD); 40 | strcpy(envData.mqttClientId, MQTT_CLIENT_ID); 41 | envData.mqttServerPort = MQTT_PORT; 42 | #endif 43 | #ifdef USE_MQTT_HOME_ASSISTANT 44 | strcpy(envData.mqttHADeviceId, MQTT_HOME_ASSISTANT_DEVICE_ID); 45 | strcpy(envData.mqttHADeviceName, MQTT_HOME_ASSISTANT_DEVICE_NAME); 46 | #endif 47 | 48 | #ifdef USE_OTA_UPDATE 49 | strcpy(envData.otaHostname, OTA_HOSTNAME); 50 | strcpy(envData.otaPassword, OTA_PASS); 51 | #endif 52 | 53 | #ifdef USE_NTP_SERVER 54 | strcpy(envData.ntpServer, NTP_SERVER_CONNECT_TO); 55 | strcpy(envData.ntpTimezone, CURRENT_TIMEZONE); 56 | #endif 57 | 58 | // END OF LOAD FROM config.h 59 | 60 | #if defined USE_WIFI_AP_CONFIGURATION 61 | if (!LittleFS.begin()) { 62 | LittleFS.format(); 63 | } 64 | // load from file 65 | if (!LittleFS.exists(CONFIG_PERSISTENCE)) { 66 | // no file found 67 | debugPrintln("No configuration file found"); 68 | } else { 69 | debugPrintln("Restoring configuration from file"); 70 | // file exists, reading and loading 71 | File configFile = LittleFS.open(CONFIG_PERSISTENCE, "r"); 72 | if (!configFile) { 73 | debugPrintln("ERROR: cannot open config file"); 74 | } else { 75 | size_t size = configFile.size(); 76 | DynamicJsonDocument doc(size * 3); 77 | DeserializationError error = deserializeJson(doc, configFile); 78 | if (error) { 79 | debugPrintln("ERROR: Cannot deserialize settings from file"); 80 | debugPrintln(error.c_str()); 81 | } else { 82 | if (doc.containsKey(CONFIG_SERIAL_DEBUG)) { 83 | envData.serialDebug = doc[CONFIG_SERIAL_DEBUG]; 84 | } 85 | 86 | loadStringToEnvIfExist(doc, CONFIG_WIFI_SSID, envData.wifiSSID); 87 | loadStringToEnvIfExist(doc, CONFIG_WIFI_PASSWORD, envData.wifiPassword); 88 | 89 | loadStringToEnvIfExist(doc, CONFIG_WIFI_IP_ADDRESS, envData.wifiIp); 90 | loadStringToEnvIfExist(doc, CONFIG_WIFI_GATEWAY, envData.wifiGateway); 91 | loadStringToEnvIfExist(doc, CONFIG_WIFI_SUBNET, envData.wifiSubnet); 92 | loadStringToEnvIfExist(doc, CONFIG_WIFI_DNS1, envData.wifiDns1); 93 | loadStringToEnvIfExist(doc, CONFIG_WIFI_DNS2, envData.wifiDns2); 94 | 95 | loadStringToEnvIfExist(doc, CONFIG_WM_AP_SSID, envData.wmApSSID); 96 | loadStringToEnvIfExist(doc, CONFIG_WM_AP_PASSWORD, envData.wmApPassword); 97 | 98 | #if defined USE_BLYNK 99 | loadStringToEnvIfExist(doc, CONFIG_BLYNK_AUTH, envData.blynkAuth); 100 | #ifndef USE_BLYNK_2 101 | loadStringToEnvIfExist(doc, CONFIG_BLYNK_HOSTNAME, envData.blynkServerHostname); 102 | 103 | if (doc.containsKey(CONFIG_BLYNK_PORT)) { 104 | envData.blynkServerPort = doc[CONFIG_BLYNK_PORT]; 105 | } 106 | #endif 107 | #endif 108 | #ifdef USE_MQTT 109 | loadStringToEnvIfExist(doc, CONFIG_MQTT_HOSTNAME, envData.mqttServerHostname); 110 | loadStringToEnvIfExist(doc, CONFIG_MQTT_PASSWORD, envData.mqttPassword); 111 | loadStringToEnvIfExist(doc, CONFIG_MQTT_USERNAME, envData.mqttUsername); 112 | loadStringToEnvIfExist(doc, CONFIG_MQTT_CLIENT_ID, envData.mqttClientId); 113 | if (doc.containsKey(CONFIG_MQTT_PORT)) 114 | envData.mqttServerPort = doc[CONFIG_MQTT_PORT]; 115 | 116 | #endif 117 | #ifdef USE_MQTT_HOME_ASSISTANT 118 | loadStringToEnvIfExist(doc, CONFIG_MQTT_HA_DEVICE_ID, envData.mqttHADeviceId); 119 | loadStringToEnvIfExist(doc, CONFIG_MQTT_HA_DEVICE_NAME, envData.mqttHADeviceName); 120 | #endif 121 | 122 | #ifdef USE_OTA_UPDATE 123 | loadStringToEnvIfExist(doc, CONFIG_OTA_HOSTNAME, envData.otaHostname); 124 | loadStringToEnvIfExist(doc, CONFIG_OTA_PASSWORD, envData.otaPassword); 125 | #endif 126 | 127 | #ifdef USE_NTP_SERVER 128 | loadStringToEnvIfExist(doc, CONFIG_NTP_SERVER, envData.ntpServer); 129 | loadStringToEnvIfExist(doc, CONFIG_NTP_TIMEZONE, envData.ntpTimezone); 130 | #endif 131 | } 132 | } 133 | } 134 | LittleFS.end(); 135 | #endif 136 | } 137 | 138 | void Environment::loadStringToEnvIfExist(DynamicJsonDocument doc, const char *envKey, char *envValue) { 139 | if (doc.containsKey(envKey)) strcpy(envValue, doc[envKey]); 140 | } 141 | 142 | void Environment::resetEnvData() { 143 | LittleFS.begin(); 144 | // load from file 145 | if (LittleFS.exists(CONFIG_PERSISTENCE)) { 146 | LittleFS.remove(CONFIG_PERSISTENCE); 147 | } 148 | LittleFS.end(); 149 | } 150 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/Environment.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef ENVIRONMENT_H 25 | #define ENVIRONMENT_H 26 | 27 | #include "../core/debug.h" 28 | #include "../incl/include_all_core.h" 29 | #include "../incl/include_all_lib.h" 30 | 31 | struct EnvironrmentData { 32 | bool serialDebug = false; 33 | // wifi 34 | char wifiSSID[CONFIG_WIFI_SSID_LEN + 1] = WIFI_SSID; 35 | char wifiPassword[CONFIG_WIFI_PASSWORD_LEN + 1]; 36 | char wifiIp[CONFIG_WIFI_IP_ADDRESS_LEN + 1]; 37 | char wifiGateway[CONFIG_WIFI_GATEWAY_LEN + 1]; 38 | char wifiSubnet[CONFIG_WIFI_SUBNET_LEN + 1]; 39 | char wifiDns1[CONFIG_WIFI_DNS1_LEN + 1]; 40 | char wifiDns2[CONFIG_WIFI_DNS2_LEN + 1]; 41 | // wifi manager 42 | #ifdef USE_WIFI_AP_CONFIGURATION 43 | char wmApSSID[CONFIG_WM_AP_SSID_LEN + 1]; 44 | char wmApPassword[CONFIG_WM_AP_PASSWORD_LEN + 1]; 45 | #endif 46 | // blynk 47 | #ifdef USE_BLYNK 48 | #ifndef USE_BLYNK_2 49 | char blynkServerHostname[CONFIG_BLYNK_HOSTNAME_LEN + 1]; 50 | uint16_t blynkServerPort; 51 | #endif 52 | char blynkAuth[CONFIG_BLYNK_AUTH_LEN + 1]; 53 | #endif 54 | // mqtt 55 | #ifdef USE_MQTT 56 | char mqttServerHostname[CONFIG_MQTT_HOSTNAME_LEN + 1]; 57 | uint16_t mqttServerPort; 58 | char mqttUsername[CONFIG_MQTT_USERNAME_LEN + 1]; 59 | char mqttPassword[CONFIG_MQTT_PASSWORD_LEN + 1]; 60 | char mqttClientId[CONFIG_MQTT_CLIENT_ID_LEN + 1]; 61 | #endif 62 | #ifdef USE_MQTT_HOME_ASSISTANT 63 | char mqttHADeviceId[CONFIG_MQTT_HA_DEVICE_ID_LEN + 1]; 64 | char mqttHADeviceName[CONFIG_MQTT_HA_DEVICE_NAME_LEN + 1]; 65 | #endif 66 | #ifdef USE_OTA_UPDATE 67 | char otaHostname[CONFIG_OTA_HOSTNAME_LEN + 1]; 68 | char otaPassword[CONFIG_OTA_PASSWORD_LEN + 1]; 69 | #endif 70 | #ifdef USE_NTP_SERVER 71 | char ntpServer[CONFIG_NTP_SERVER_LEN + 1]; 72 | char ntpTimezone[CONFIG_NTP_TIMEZONE_LEN + 1]; 73 | #endif 74 | #ifdef USE_EXTERNAL_HEAVY_LOAD_CURRENT_METER 75 | float heavyLoadCurrentZeroV = EXTERNAL_HEAVY_LOAD_CURRENT_METER_VOLTAGE_ZERO_AMP_VOLT; 76 | #endif 77 | }; 78 | 79 | class Environment { 80 | public: 81 | static void loadEnvData(); 82 | 83 | static void resetEnvData(); 84 | 85 | static const EnvironrmentData *getData() { 86 | return &envData; 87 | } 88 | 89 | private: 90 | static void loadStringToEnvIfExist(DynamicJsonDocument doc, const char *envKey, char *envValue); 91 | 92 | static EnvironrmentData envData; 93 | }; 94 | 95 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/Text.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef TEXT_H 25 | #define TEXT_H 26 | 27 | class Text { 28 | public: 29 | static constexpr const char *ok = "OK"; 30 | static constexpr const char *ko = "KO"; 31 | static constexpr const char *dot = "."; 32 | static constexpr const char *password = "Password"; 33 | static constexpr const char *connecting = "Connecting "; 34 | static constexpr const char *setupWithName = "++ SETTING UP %s"; 35 | static constexpr const char *errorWithCode = "Error[%i]"; 36 | static constexpr const char *errorWithCodeText = "Error[%i] %s"; 37 | static constexpr const char *errorWithCodeInt = "Error[%i] %i"; 38 | static constexpr const char *port = "Port"; 39 | static constexpr const char *server = "Server"; 40 | static constexpr const char *syncErrorWithCountAndType = "WARNING %i %s var. are not synced"; 41 | static constexpr const char *syncErrorWithVariable = "WARNING \"%s\" is not synced"; 42 | }; 43 | 44 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/Util.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 5 | * Copyright (c) 2021 Alberto Bettin 6 | * 7 | * Based on the work of @jaminNZx and @tekk. 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | #include "Util.h" 25 | 26 | #define UTIL_MAX_DEC_DIV 1000 27 | 28 | uint8_t Util::digits(int number) { 29 | if (number < 0) return Util::digits(-number); 30 | if (number < 10) return 1; 31 | return 1 + Util::digits(number / 10); 32 | } 33 | 34 | char *Util::sharedBuffer = new char[256]; 35 | 36 | char *Util::intToChar(int v, char *buf) { 37 | itoa(v, buf, 10); 38 | return buf; 39 | } 40 | 41 | char *Util::floatToChar(float v, char *buf) { 42 | uint8_t index = 0; 43 | if (v < 0) { 44 | buf[index++] = '-'; 45 | } 46 | 47 | int iValue = (int)v; 48 | int dValue = (v - iValue) * UTIL_MAX_DEC_DIV; 49 | dValue = dValue < 0 ? -dValue : dValue; 50 | 51 | itoa(iValue, buf + index, 10); 52 | index += Util::digits(iValue); 53 | 54 | if (dValue >= 1) { 55 | buf[index++] = '.'; 56 | int decMissPosition = Util::digits(UTIL_MAX_DEC_DIV) - Util::digits(dValue); 57 | while (--decMissPosition > 0) { 58 | buf[index++] = '0'; 59 | } 60 | itoa(dValue, buf + index, 10); 61 | } 62 | return buf; 63 | } 64 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/Util.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef UTIL_H 25 | #define UTIL_H 26 | 27 | #include 28 | 29 | class Util { 30 | public: 31 | static char *intToChar(int v, char *buf); 32 | static char *intToChar(int v) { 33 | return intToChar(v, sharedBuffer); 34 | } 35 | static char *floatToChar(float v, char *buf); 36 | static char *floatToChar(float v) { 37 | return floatToChar(v, sharedBuffer); 38 | } 39 | 40 | static uint8_t digits(int number); 41 | 42 | /** 43 | * Shared buffer, use it with caution as it will be reused 44 | * 45 | */ 46 | static char *sharedBuffer; 47 | }; 48 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/VariableDefiner.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef VariableDefiner_h 25 | #define VariableDefiner_h 26 | 27 | #include "../incl/include_all_blynk_vpin.h" 28 | #include "../incl/include_all_core.h" 29 | #include "../incl/include_all_mqtt_topic.h" 30 | 31 | typedef enum { 32 | SR_REALTIME, 33 | SR_STATS, 34 | SR_INTERNAL 35 | } VariableSource; 36 | 37 | typedef enum { 38 | MD_READ, 39 | MD_READWRITE 40 | } VariableMode; 41 | 42 | typedef enum { 43 | DT_UNDEFINED, 44 | DT_STRING, 45 | DT_FLOAT, 46 | DT_BOOL, 47 | DT_UINT16 48 | } VariableDatatype; 49 | 50 | typedef enum { 51 | UOM_UNDEFINED, 52 | UOM_STATUS, 53 | UOM_TRIGGER, 54 | UOM_PERCENT, 55 | UOM_VOLT, 56 | UOM_WATT, 57 | UOM_KILOWATTHOUR, 58 | UOM_AMPERE, 59 | UOM_AMPEREHOUR, 60 | UOM_TEMPERATURE_C, 61 | UOM_MINUTE 62 | } VariableUOM; 63 | 64 | typedef enum { 65 | PV_VOLTAGE, 66 | PV_POWER, 67 | PV_CURRENT, 68 | LOAD_CURRENT, 69 | LOAD_POWER, 70 | BATTERY_TEMP, 71 | BATTERY_VOLTAGE, 72 | BATTERY_SOC, 73 | CONTROLLER_TEMP, 74 | BATTERY_CHARGE_CURRENT, 75 | BATTERY_CHARGE_POWER, 76 | BATTERY_OVERALL_CURRENT, 77 | REALTIME_CLOCK, 78 | LOAD_FORCE_ONOFF, 79 | LOAD_MANUAL_ONOFF, 80 | REMOTE_BATTERY_TEMP, 81 | GENERATED_ENERGY_TODAY, 82 | GENERATED_ENERGY_MONTH, 83 | GENERATED_ENERGY_YEAR, 84 | GENERATED_ENERGY_TOTAL, 85 | MAXIMUM_PV_VOLTAGE_TODAY, 86 | MINIMUM_PV_VOLTAGE_TODAY, 87 | MAXIMUM_BATTERY_VOLTAGE_TODAY, 88 | MINIMUM_BATTERY_VOLTAGE_TODAY, 89 | BATTERY_BOOST_VOLTAGE, 90 | BATTERY_EQUALIZATION_VOLTAGE, 91 | BATTERY_FLOAT_VOLTAGE, 92 | BATTERY_FLOAT_MIN_VOLTAGE, 93 | BATTERY_CHARGING_LIMIT_VOLTAGE, 94 | BATTERY_DISCHARGING_LIMIT_VOLTAGE, 95 | BATTERY_LOW_VOLTAGE_DISCONNECT, 96 | BATTERY_LOW_VOLTAGE_RECONNECT, 97 | BATTERY_OVER_VOLTAGE_DISCONNECT, 98 | BATTERY_OVER_VOLTAGE_RECONNECT, 99 | BATTERY_UNDER_VOLTAGE_SET, 100 | BATTERY_UNDER_VOLTAGE_RESET, 101 | BATTERY_STATUS_TEXT, 102 | CHARGING_EQUIPMENT_STATUS_TEXT, 103 | DISCHARGING_EQUIPMENT_STATUS_TEXT, 104 | CHARGING_DEVICE_ONOFF, 105 | HEATSINK_TEMP, 106 | BATTERY_RATED_VOLTAGE, // 0 - auto detect, otherwise specify the voltage of the battery 107 | BATTERY_TYPE, // 0 - custom, 1 - Sealed / AGM, 2 - GEL, 3 - Flooded / Wet Cell 108 | BATTERY_CAPACITY, 109 | BATTERY_EQUALIZATION_DURATION, 110 | BATTERY_BOOST_DURATION, 111 | BATTERY_TEMPERATURE_COMPENSATION_COEFFICIENT, 112 | BATTERY_MANAGEMENT_MODE, // 0 - voltage compensation, 1 - SOC 113 | CONSUMED_ENERGY_TODAY, 114 | CONSUMED_ENERGY_MONTH, 115 | CONSUMED_ENERGY_YEAR, 116 | CONSUMED_ENERGY_TOTAL, 117 | //---------------- 118 | INTERNAL_STATUS, 119 | INTERNAL_DEBUG, 120 | //---------------- 121 | UPDATE_ALL_CONTROLLER_DATA, 122 | //---------------- 123 | VARIABLES_COUNT 124 | } Variable; 125 | 126 | struct VariableDefinition { 127 | Variable variable; 128 | const char *text; 129 | VariableDatatype datatype; 130 | VariableUOM uom; 131 | VariableSource source; 132 | VariableMode mode; 133 | const uint8_t *blynkVPin; 134 | const char *mqttTopic; 135 | }; 136 | 137 | class VariableDefiner { 138 | public: 139 | static VariableDefiner &getInstance() { 140 | static VariableDefiner instance; 141 | return instance; 142 | } 143 | 144 | const VariableDefinition *getDefinition(Variable variable); 145 | 146 | const VariableDefinition *getDefinitionByBlynkVPin(uint8_t pin); 147 | 148 | const VariableDefinition *getDefinitionByMqttTopic(const char *mqttTopic); 149 | 150 | VariableDatatype getDatatype(Variable variable); 151 | 152 | bool isFromScc(const Variable variable) { 153 | return this->variables[variable].source != VariableSource::SR_INTERNAL; 154 | } 155 | 156 | bool isValueEqual(Variable variable, const void *val1, const void *val2) { 157 | uint8_t valueSize = this->getVariableSize(variable); 158 | if (valueSize > 0) { 159 | return memcmp(val1, val2, valueSize) == 0; 160 | } 161 | return false; 162 | } 163 | 164 | uint8_t getVariableSize(Variable variable); 165 | 166 | private: 167 | VariableDefiner(); 168 | 169 | void initializeVariable(Variable variable, const char *text, VariableDatatype datatype, VariableUOM uom, VariableSource source, VariableMode mode, uint8_t *blynkPin, const char *mqttTopic); 170 | 171 | VariableDefinition *variables = new VariableDefinition[Variable::VARIABLES_COUNT](); 172 | }; 173 | 174 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/datetime.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef DATETIME_H 25 | #define DATETIME_H 26 | 27 | #include "../core/Environment.h" 28 | #include "../incl/include_all_core.h" 29 | 30 | class Datetime { 31 | public: 32 | #ifdef USE_NTP_SERVER 33 | static bool setupDatetimeFromNTP() { 34 | uint8_t maxCount = 20; 35 | debugPrint(Text::connecting); 36 | configTzTime(Environment::getData()->ntpTimezone, Environment::getData()->ntpServer); 37 | 38 | while (time(nullptr) < 100000ul && --maxCount > 0) { 39 | debugPrint(Text::dot); 40 | delay(500); 41 | } 42 | debugPrintln(maxCount > 0 ? Text::ok : Text::ko); 43 | return maxCount > 0; 44 | } 45 | #endif 46 | 47 | static struct tm *getMyNowTm() { 48 | time_t tnow = time(nullptr) + 1; 49 | return tnow <= 100000ul ? nullptr : localtime(&tnow); 50 | } 51 | }; 52 | 53 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/debug.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #include "debug.h" 23 | #include // vsnprintf 24 | 25 | #include "../incl/include_all_core.h" 26 | 27 | #define DEBUG_REGISTER_CALLBACKS_MAX 2 28 | 29 | bool debugEnabled = true; 30 | 31 | void setDebugEnabled(bool enabled) 32 | { 33 | debugEnabled = enabled; 34 | } 35 | 36 | uint8_t regCallbacksIndex = 0; 37 | void (*regCallbacks[DEBUG_REGISTER_CALLBACKS_MAX])(String); 38 | 39 | void debugAddRegisterCallback(void (*regCallback)(String)) 40 | { 41 | if (regCallbacksIndex < DEBUG_REGISTER_CALLBACKS_MAX) 42 | { 43 | regCallbacks[regCallbacksIndex++] = regCallback; 44 | } 45 | } 46 | 47 | void debugDispactMessageRegisterCallback(String msg) 48 | { 49 | for (uint8_t index = 0; index < regCallbacksIndex; index++) 50 | { 51 | (*regCallbacks[index])(msg); 52 | } 53 | } 54 | 55 | void debugPrint(String message) 56 | { 57 | if (debugEnabled) 58 | { 59 | BOARD_DEBUG_SERIAL_STREAM.print(message); 60 | } 61 | for (uint8_t index = 0; index < regCallbacksIndex; index++) 62 | { 63 | (*regCallbacks[index])(message); 64 | } 65 | } 66 | 67 | void debugPrintln() 68 | { 69 | debugPrint("\r\n"); 70 | } 71 | 72 | void debugPrintln(String msgString) 73 | { 74 | debugPrint(msgString + "\r\n"); 75 | } 76 | 77 | void debugPrintln(const char *msgChar) 78 | { 79 | debugPrintln(String(msgChar)); 80 | } 81 | 82 | void debugPrint(const char *msgChar) 83 | { 84 | debugPrint(String(msgChar)); 85 | } 86 | 87 | void debugPrintln(int num) 88 | { 89 | debugPrintln(String(num)); 90 | } 91 | 92 | void debugPrint(const int num) 93 | { 94 | debugPrint(String(num)); 95 | } 96 | 97 | void debugPrintln(unsigned char num) 98 | { 99 | debugPrintln(String(num)); 100 | } 101 | 102 | void debugPrint(unsigned char num) 103 | { 104 | debugPrint(String(num)); 105 | } 106 | 107 | void debugPrintf(bool newLine, const char *format, ...) 108 | { 109 | va_list args; 110 | va_start(args, format); 111 | vsnprintf(Util::sharedBuffer, 256, format, args); 112 | newLine ? debugPrintln(String(Util::sharedBuffer)) : debugPrint(String(Util::sharedBuffer)); 113 | va_end(args); 114 | } 115 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/core/debug.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef DEBUG_H 25 | #define DEBUG_H 26 | 27 | #include "../incl/include_all_core.h" 28 | void setDebugEnabled(bool enable); 29 | void debugAddRegisterCallback(void (*regCallback)(String)); 30 | void debugDispactMessageRegisterCallback(String msg); 31 | void debugPrint(String message); 32 | void debugPrintln(); 33 | void debugPrintln(const String msgString); 34 | void debugPrintln(const char *msgChar); 35 | void debugPrint(const char *msgChar); 36 | void debugPrintln(int num); 37 | void debugPrint(int num); 38 | void debugPrintln(unsigned char num); 39 | void debugPrint(unsigned char num); 40 | void debugPrintf(bool newLine, const char *format, ...); 41 | 42 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/feature/BlynkSync.cpp: -------------------------------------------------------------------------------- 1 | #include "BlynkSync.h" 2 | 3 | #include "../incl/include_all_core.h" 4 | 5 | #ifdef USE_BLYNK 6 | 7 | #include "../core/Environment.h" 8 | #include "../core/datetime.h" 9 | #include "../incl/include_all_lib.h" 10 | 11 | // reducing Blynk footprint 12 | #define BLYNK_NO_BUILTIN // Disable built-in analog & digital pin operations 13 | #define BLYNKTIMER_H // no blynk timer - using simple timer 14 | #if defined USE_BLYNK 15 | #if defined ESP32 16 | #include 17 | #elif defined ESP8266 18 | #include 19 | #endif 20 | #endif 21 | 22 | #ifndef BLYNK_CONNECT_ATTEMPT 23 | #define BLYNK_CONNECT_ATTEMPT 10 24 | #endif 25 | 26 | #ifdef vPIN_INTERNAL_DEBUG_TERMINAL 27 | void blynkDebugCallback(String message) { 28 | Blynk.virtualWrite(vPIN_INTERNAL_DEBUG_TERMINAL, message); 29 | } 30 | #endif 31 | 32 | BlynkSync::BlynkSync() { 33 | this->renewValueCount = BLYNK_VALUE_CACHES_UNTIL_COUNT; 34 | } 35 | 36 | void BlynkSync::setup() { 37 | #ifndef BLYNK_CONNECTION_REQUIRED 38 | this->connect(true); 39 | #else 40 | this->connect(false); 41 | #endif 42 | #ifdef vPIN_INTERNAL_DEBUG_TERMINAL 43 | debugAddRegisterCallback(blynkDebugCallback); 44 | #endif 45 | } 46 | 47 | void BlynkSync::connect(bool blocking) { 48 | debugPrintf(true, Text::setupWithName, "BLYNK"); 49 | debugPrint(Text::connecting); 50 | 51 | #ifdef USE_BLYNK_2 52 | Blynk.config(Environment::getData()->blynkAuth); 53 | #else 54 | 55 | Blynk.config( 56 | Environment::getData()->blynkAuth, 57 | strlen(Environment::getData()->blynkServerHostname) ? Environment::getData()->blynkServerHostname : BLYNK_DEFAULT_DOMAIN, 58 | Environment::getData()->blynkServerPort ? Environment::getData()->blynkServerPort : BLYNK_DEFAULT_PORT); 59 | 60 | #endif 61 | 62 | uint8_t counter = 0; 63 | 64 | while (( blocking || counter < BLYNK_CONNECT_ATTEMPT) && !Blynk.connect()) { 65 | delay(500); 66 | debugPrint(Text::dot); 67 | 68 | counter++; 69 | } 70 | 71 | debugPrintln(Blynk.connected() ? Text::ok : Text::ko); 72 | Controller::getInstance().setErrorFlag(STATUS_ERR_NO_BLYNK_CONNECTION, false); 73 | } 74 | 75 | void BlynkSync::loop() { 76 | Controller::getInstance().setErrorFlag(STATUS_ERR_NO_BLYNK_CONNECTION, !Blynk.connected()); 77 | Blynk.run(); 78 | } 79 | 80 | bool BlynkSync::sendUpdateToVariable(const VariableDefinition *def, const void *value) { 81 | if (def->blynkVPin != nullptr) { 82 | switch (def->datatype) { 83 | case VariableDatatype::DT_BOOL: { 84 | Blynk.virtualWrite(*def->blynkVPin, *(bool *)value); 85 | return true; 86 | } break; 87 | case VariableDatatype::DT_FLOAT: { 88 | Blynk.virtualWrite(*def->blynkVPin, *(float *)value); 89 | return true; 90 | } break; 91 | case VariableDatatype::DT_UINT16: { 92 | Blynk.virtualWrite(*def->blynkVPin, *(uint16_t *)value); 93 | return true; 94 | } break; 95 | case VariableDatatype::DT_STRING: { 96 | Blynk.virtualWrite(*def->blynkVPin, (const char *)value); 97 | return true; 98 | } 99 | } 100 | } 101 | return false; 102 | } 103 | 104 | // upload values stats 105 | void BlynkSync::uploadStatsToBlynk() { 106 | if (!Blynk.connected()) { 107 | return; 108 | } 109 | 110 | BlynkSync::getInstance().sendUpdateAllBySource(VariableSource::SR_STATS, false); 111 | } 112 | 113 | // upload values realtime 114 | void BlynkSync::uploadRealtimeToBlynk() { 115 | if (!Blynk.connected()) { 116 | return; 117 | } 118 | 119 | #ifdef vPIN_INTERNAL_STATUS 120 | uint16_t status = Controller::getInstance().getStatus(); 121 | this->sendUpdateToVariable(VariableDefiner::getInstance().getDefinition(Variable::INTERNAL_STATUS), &(status)); 122 | #endif 123 | this->sendUpdateAllBySource(VariableSource::SR_REALTIME, false); 124 | } 125 | 126 | BLYNK_WRITE_DEFAULT() { 127 | const VariableDefinition *def = VariableDefiner::getInstance().getDefinitionByBlynkVPin(request.pin); 128 | if (def != nullptr) { 129 | if (def->source == VariableSource::SR_INTERNAL) { 130 | switch (def->variable) { 131 | case Variable::REALTIME_CLOCK: { 132 | if (param.asInt() > 0) { 133 | debugPrintln("UPDATE CONTROLLER DATETIME"); 134 | if (Datetime::getMyNowTm() != nullptr) { 135 | Controller::getInstance().getSolarController()->syncRealtimeClock(Datetime::getMyNowTm()); 136 | } 137 | Blynk.virtualWrite(*def->blynkVPin, 0); 138 | } 139 | } break; 140 | case Variable::UPDATE_ALL_CONTROLLER_DATA: { 141 | if (param.asInt() > 0) { 142 | debugPrintln("REQUEST ALL VALUES TO CONTROLLER"); 143 | Controller::getInstance().getSolarController()->fetchAllValues(); 144 | BlynkSync::getInstance().uploadRealtimeToBlynk(); 145 | BlynkSync::getInstance().uploadStatsToBlynk(); 146 | 147 | Blynk.virtualWrite(*def->blynkVPin, 0); 148 | } 149 | } break; 150 | } 151 | } else if (Controller::getInstance().getSolarController()->isVariableEnabled(def->variable)) { 152 | switch (def->datatype) { 153 | case VariableDatatype::DT_UINT16: { 154 | uint16_t newState = param.asInt(); 155 | BlynkSync::getInstance().applyUpdateToVariable(def->variable, &newState, false); 156 | } break; 157 | case VariableDatatype::DT_FLOAT: { 158 | float newState = param.asFloat(); 159 | BlynkSync::getInstance().applyUpdateToVariable(def->variable, &newState, false); 160 | } break; 161 | case VariableDatatype::DT_BOOL: { 162 | bool newState = param.asInt() > 0; 163 | BlynkSync::getInstance().applyUpdateToVariable(def->variable, &newState, false); 164 | } break; 165 | } 166 | } 167 | } 168 | } 169 | 170 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/feature/BlynkSync.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef BLYNK_SYNC_H 25 | #define BLYNK_SYNC_H 26 | 27 | #include "../incl/include_all_core.h" 28 | 29 | #ifdef USE_BLYNK 30 | 31 | #include "../core/BaseSync.h" 32 | #include "../core/Controller.h" 33 | #include "../core/VariableDefiner.h" 34 | #include "../incl/include_all_lib.h" 35 | 36 | #define BLYNK_CONNECT_ATTEMPT 3 37 | #define BLYNK_VALUE_CACHES_UNTIL_COUNT 15 38 | 39 | #ifdef vPIN_INTERNAL_DEBUG_TERMINAL 40 | void blynkDebugCallback(String message); 41 | #endif 42 | 43 | class BlynkSync : public BaseSync { 44 | public: 45 | static BlynkSync &getInstance() { 46 | static BlynkSync instance; 47 | return instance; 48 | } 49 | 50 | void setup(); 51 | void connect(bool blocking = true); 52 | void loop(); 53 | inline bool isVariableAllowed(const VariableDefinition *def); 54 | bool sendUpdateToVariable(const VariableDefinition *def, const void *value); 55 | // upload values stats 56 | void uploadStatsToBlynk(); 57 | // upload values realtime 58 | void uploadRealtimeToBlynk(); 59 | 60 | private: 61 | BlynkSync(); 62 | }; 63 | 64 | bool BlynkSync::isVariableAllowed(const VariableDefinition *def) { 65 | return def->blynkVPin != nullptr; 66 | } 67 | 68 | #endif 69 | #endif 70 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/feature/MqttHASync.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #include "MqttHASync.h" 23 | 24 | #include "../core/datetime.h" 25 | #include "../incl/include_all_core.h" 26 | 27 | #ifdef USE_MQTT_HOME_ASSISTANT 28 | 29 | char mqttPublishBuffer[20]; 30 | 31 | #define RETAIN_ALL_MSG false 32 | #define MQTT_CONNECT_ATTEMPT 3 33 | 34 | // every setValue/setState will trigger mqttCallbacks, 35 | bool ignoreCallback = false; 36 | 37 | inline const char *getVariableUOM(VariableUOM uom) { 38 | switch (uom) { 39 | case UOM_TEMPERATURE_C: 40 | return "°C"; 41 | case UOM_WATT: 42 | return "W"; 43 | case UOM_KILOWATTHOUR: 44 | return "kWh"; 45 | case UOM_PERCENT: 46 | return "%"; 47 | case UOM_AMPERE: 48 | return "A"; 49 | case UOM_VOLT: 50 | return "V"; 51 | case UOM_MINUTE: 52 | return "min"; 53 | } 54 | return nullptr; 55 | } 56 | 57 | void onMqttNumberCallback(HANumeric value, HANumber *el) { 58 | if (!ignoreCallback) { 59 | MqttHASync haSync = MqttHASync::getInstance(); 60 | Variable var = haSync.findVariableBySensor(el); 61 | if (var < Variable::VARIABLES_COUNT) { 62 | switch (VariableDefiner::getInstance().getDatatype(var)) { 63 | case DT_UINT16: { 64 | uint16_t rValue = value.toUInt16(); 65 | haSync.applyUpdateToVariable(var, &rValue, false); 66 | } break; 67 | case DT_FLOAT: { 68 | float rValue = value.toFloat(); 69 | haSync.applyUpdateToVariable(var, &rValue, false); 70 | } break; 71 | } 72 | } 73 | } 74 | } 75 | 76 | void onMqttBoolButtonCallback(HAButton *el) { 77 | if (!ignoreCallback) { 78 | MqttHASync haSync = MqttHASync::getInstance(); 79 | Variable var = haSync.findVariableBySensor(el); 80 | if (var < Variable::VARIABLES_COUNT) { 81 | switch (var) { 82 | case Variable::REALTIME_CLOCK: 83 | debugPrintln("UPDATE CONTROLLER DATETIME"); 84 | if (Datetime::getMyNowTm() != nullptr) { 85 | Controller::getInstance().getSolarController()->syncRealtimeClock(Datetime::getMyNowTm()); 86 | } 87 | break; 88 | case Variable::UPDATE_ALL_CONTROLLER_DATA: 89 | debugPrintln("REQUEST ALL VALUES TO CONTROLLER"); 90 | Controller::getInstance().getSolarController()->fetchAllValues(); 91 | MqttHASync::getInstance().uploadRealtimeToMqtt(); 92 | MqttHASync::getInstance().uploadStatsToMqtt(); 93 | break; 94 | } 95 | } 96 | } 97 | } 98 | 99 | void onMqttBoolSwitchCallback(bool value, HASwitch *el) { 100 | if (!ignoreCallback) { 101 | MqttHASync haSync = MqttHASync::getInstance(); 102 | Variable var = haSync.findVariableBySensor(el); 103 | if (var < Variable::VARIABLES_COUNT) { 104 | haSync.applyUpdateToVariable(var, &value, false); 105 | } 106 | } 107 | } 108 | 109 | void setupHASensor(HASensor *sensor, const VariableUOM *uom) { 110 | switch (*uom) { 111 | case UOM_TEMPERATURE_C: 112 | sensor->setDeviceClass("temperature"); 113 | break; 114 | case UOM_WATT: 115 | sensor->setDeviceClass("power"); 116 | break; 117 | case UOM_KILOWATTHOUR: 118 | sensor->setDeviceClass("energy"); 119 | break; 120 | case UOM_PERCENT: 121 | sensor->setUnitOfMeasurement("%"); 122 | break; 123 | case UOM_AMPERE: 124 | sensor->setDeviceClass("current"); 125 | break; 126 | case UOM_VOLT: 127 | sensor->setDeviceClass("voltage"); 128 | break; 129 | } 130 | sensor->setUnitOfMeasurement(getVariableUOM(*uom)); 131 | sensor->setValue(nullptr); 132 | } 133 | 134 | MqttHASync::MqttHASync() : BaseSync() { 135 | this->renewValueCount = 0; 136 | 137 | WiFiClient *wifiClient = new WiFiClient; 138 | 139 | device = new HADevice(Environment::getData()->mqttClientId); 140 | mqtt = new HAMqtt(*wifiClient, *device, VARIABLES_COUNT); 141 | } 142 | 143 | void MqttHASync::setup() { 144 | // set device's details 145 | 146 | device->setName(Environment::getData()->mqttHADeviceName); 147 | device->setManufacturer(PROJECT_AUTHOR); 148 | device->setModel(PROJECT_NAME); 149 | device->setSoftwareVersion(PROJECT_VERSION); 150 | device->setConfigurationUrl(WiFi.localIP().toString().c_str()); 151 | device->enableSharedAvailability(); 152 | device->enableLastWill(); 153 | 154 | for (uint8_t index = 0; index < Variable::VARIABLES_COUNT; index++) { 155 | const VariableDefinition *def = VariableDefiner::getInstance().getDefinition((Variable)index); 156 | 157 | if (def->mqttTopic != nullptr && (def->source == VariableSource::SR_INTERNAL || Controller::getInstance().getSolarController()->isVariableEnabled(def->variable) || Controller::getInstance().getSolarController()->isVariableOverWritten(def->variable))) { 158 | haSensors[index] = nullptr; 159 | switch (def->datatype) { 160 | case DT_BOOL: 161 | if (def->mode == MD_READWRITE) { 162 | if (def->uom == UOM_TRIGGER) { 163 | HAButton *haButton = new HAButton(def->mqttTopic); 164 | haButton->onCommand(onMqttBoolButtonCallback); 165 | haSensors[index] = haButton; 166 | } else { 167 | HASwitch *haSwitch = new HASwitch(def->mqttTopic); 168 | haSwitch->onCommand(onMqttBoolSwitchCallback); 169 | haSensors[index] = haSwitch; 170 | } 171 | } else { 172 | haSensors[index] = new HABinarySensor(def->mqttTopic); 173 | } 174 | break; 175 | case DT_UINT16: 176 | case DT_FLOAT: 177 | if (def->mode == MD_READWRITE) { 178 | HANumber *haNumber = new HANumber( 179 | def->mqttTopic, 180 | def->datatype == DT_FLOAT ? HABaseDeviceType::PrecisionP2 : HABaseDeviceType::PrecisionP0); 181 | haNumber->onCommand(onMqttNumberCallback); 182 | haNumber->setStep(def->datatype == DT_FLOAT ? 0.01 : 1); 183 | haNumber->setUnitOfMeasurement(getVariableUOM(def->uom)); 184 | haSensors[index] = haNumber; 185 | } else { 186 | HASensorNumber *hASensor = new HASensorNumber( 187 | def->mqttTopic, 188 | def->datatype == DT_FLOAT ? HABaseDeviceType::PrecisionP2 : HABaseDeviceType::PrecisionP0); 189 | setupHASensor(hASensor, &(def->uom)); 190 | haSensors[index] = hASensor; 191 | } 192 | break; 193 | default: 194 | if (def->mode == MD_READWRITE) { 195 | HANumber *haNumber = new HANumber(def->mqttTopic); 196 | haNumber->onCommand(onMqttNumberCallback); 197 | haNumber->setStep(def->datatype == DT_FLOAT ? 0.01 : 1); 198 | haNumber->setUnitOfMeasurement(getVariableUOM(def->uom)); 199 | haSensors[index] = haNumber; 200 | } else { 201 | HASensor *hASensor = new HASensor(def->mqttTopic); 202 | setupHASensor(hASensor, &(def->uom)); 203 | haSensors[index] = hASensor; 204 | } 205 | } 206 | 207 | haSensors[index]->setName(def->text); 208 | 209 | if (strlen(Environment::getData()->mqttHADeviceId) <= 0) { 210 | haSensors[index]->setObjectId(def->mqttTopic); 211 | } else { 212 | char *idName = new char[strlen(Environment::getData()->mqttHADeviceId) + strlen(def->text) + 2]; 213 | strcpy(idName, Environment::getData()->mqttHADeviceId); 214 | strcat(idName, " "); 215 | strcat(idName, def->text); 216 | haSensors[index]->setObjectId(idName); 217 | } 218 | } 219 | } 220 | this->connect(); 221 | } 222 | 223 | Variable MqttHASync::findVariableBySensor(HABaseDeviceType *haSensor) { 224 | for (uint8_t index = 0; index < Variable::VARIABLES_COUNT; index++) { 225 | if (haSensors[index] == haSensor) { 226 | return (Variable)index; 227 | } 228 | } 229 | return Variable::VARIABLES_COUNT; 230 | } 231 | 232 | void MqttHASync::connect(bool blocking) { 233 | if (this->initialized) { 234 | mqtt->disconnect(); 235 | } 236 | this->initialized = false; 237 | debugPrintf(true, Text::setupWithName, "MQTT-HA"); 238 | 239 | uint8_t counter; 240 | 241 | do { 242 | counter = 0; 243 | debugPrint(Text::connecting); 244 | if (!initialized) { 245 | initialized = mqtt->begin( 246 | Environment::getData()->mqttServerHostname, 247 | Environment::getData()->mqttServerPort, 248 | strlen(Environment::getData()->mqttUsername) > 0 ? Environment::getData()->mqttUsername : nullptr, 249 | strlen(Environment::getData()->mqttPassword) > 0 ? Environment::getData()->mqttPassword : nullptr); 250 | } 251 | mqtt->loop(); 252 | 253 | while (!mqtt->isConnected() && counter < 10) { 254 | debugPrint(Text::dot); 255 | delay(500); 256 | counter++; 257 | } 258 | if (mqtt->getState() != HAMqtt::StateConnected) { 259 | debugPrintf(true, Text::errorWithCode, mqtt->getState()); 260 | } else { 261 | debugPrintln(Text::ok); 262 | } 263 | } while (blocking && !mqtt->isConnected()); 264 | Controller::getInstance().setErrorFlag(STATUS_ERR_NO_MQTT_CONNECTION, !mqtt->isConnected()); 265 | } 266 | void MqttHASync::loop() { 267 | Controller::getInstance().setErrorFlag(STATUS_ERR_NO_MQTT_CONNECTION, !mqtt->isConnected()); 268 | mqtt->loop(); 269 | } 270 | bool MqttHASync::isVariableAllowed(const VariableDefinition *def) { 271 | return def->mqttTopic != nullptr; 272 | } 273 | bool MqttHASync::sendUpdateToVariable(const VariableDefinition *def, const void *value) { 274 | HABaseDeviceType *sensor = haSensors[def->variable]; 275 | bool result = false; 276 | ignoreCallback = true; 277 | switch (def->datatype) { 278 | case VariableDatatype::DT_UINT16: 279 | result = def->mode == MD_READ 280 | ? ((HASensorNumber *)sensor)->setValue(*(uint16_t *)value) 281 | : ((HANumber *)sensor)->setState(*(uint16_t *)value); 282 | break; 283 | case VariableDatatype::DT_FLOAT: 284 | result = def->mode == MD_READ 285 | ? ((HASensorNumber *)sensor)->setValue(*(float *)value) 286 | : ((HANumber *)sensor)->setState(*(float *)value); 287 | break; 288 | case VariableDatatype::DT_BOOL: 289 | result = def->uom != UOM_TRIGGER 290 | ? def->mode == MD_READ 291 | ? ((HASwitch *)sensor)->setState(*(bool *)value) 292 | : ((HABinarySensor *)sensor)->setState(*(bool *)value) 293 | : false; 294 | break; 295 | default: 296 | result = ((HASensor *)sensor)->setValue((const char *)value); 297 | break; 298 | } 299 | ignoreCallback = false; 300 | return result; 301 | } 302 | 303 | // upload values stats 304 | void MqttHASync::uploadStatsToMqtt() { 305 | if (!this->mqtt->isConnected()) { 306 | return; 307 | } 308 | 309 | this->sendUpdateAllBySource(VariableSource::SR_STATS, false); 310 | } 311 | 312 | // upload values realtime 313 | void MqttHASync::uploadRealtimeToMqtt() { 314 | if (!this->mqtt->isConnected()) { 315 | return; 316 | } 317 | 318 | #ifdef MQTT_TOPIC_INTERNAL_STATUS 319 | uint16_t status = Controller::getInstance().getStatus(); 320 | this->syncVariable(VariableDefiner::getInstance().getDefinition(Variable::INTERNAL_STATUS), &(status)); 321 | #endif 322 | this->sendUpdateAllBySource(VariableSource::SR_REALTIME, false); 323 | } 324 | 325 | #endif 326 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/feature/MqttHASync.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #include "../incl/include_all_core.h" 25 | 26 | #ifdef USE_MQTT_HOME_ASSISTANT 27 | 28 | #include "../core/BaseSync.h" 29 | #include "../core/Controller.h" 30 | #include "../core/VariableDefiner.h" 31 | #include "../incl/include_all_lib.h" 32 | 33 | class MqttHASync : public BaseSync { 34 | public: 35 | static MqttHASync &getInstance() { 36 | static MqttHASync instance; 37 | return instance; 38 | } 39 | 40 | void setup(); 41 | void connect(bool blocking = true); 42 | void loop(); 43 | inline bool isVariableAllowed(const VariableDefinition *def); 44 | bool sendUpdateToVariable(const VariableDefinition *def, const void *value); 45 | // upload values stats 46 | void uploadStatsToMqtt(); 47 | // upload values realtime 48 | void uploadRealtimeToMqtt(); 49 | 50 | Variable findVariableBySensor(HABaseDeviceType *haSensor); 51 | 52 | private: 53 | MqttHASync(); 54 | 55 | HADevice *device; 56 | HAMqtt *mqtt; 57 | HABaseDeviceType *haSensors[Variable::VARIABLES_COUNT]; 58 | 59 | bool initialized; 60 | }; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/feature/MqttSync.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #include "MqttSync.h" 23 | 24 | #include "../incl/include_all_core.h" 25 | 26 | #if defined(USE_MQTT) && !defined(USE_MQTT_HOME_ASSISTANT) 27 | 28 | #include "../core/datetime.h" 29 | 30 | #define RETAIN_ALL_MSG false 31 | #define MQTT_CONNECT_ATTEMPT 3 32 | 33 | #if defined(USE_MQTT_RPC_SUBSCRIBE) 34 | DynamicJsonDocument json(1024); 35 | #endif 36 | void mqttCallback(char *topic, uint8_t *bytes, unsigned int length) { 37 | String payload; 38 | for (int i = 0; i < length; i++) { 39 | payload += (char)bytes[i]; 40 | } 41 | 42 | #ifdef USE_MQTT_RPC_SUBSCRIBE 43 | deserializeJson(json, payload); 44 | const char *constTopic = json["method"].as(); 45 | payload = json["params"].as(); 46 | #else 47 | const char *constTopic = topic; 48 | #endif 49 | 50 | const VariableDefinition *def = VariableDefiner::getInstance().getDefinitionByMqttTopic(topic); 51 | 52 | if (def != nullptr && def->mode == MD_READWRITE) { 53 | if (def->source == VariableSource::SR_INTERNAL) { 54 | switch (def->variable) { 55 | case Variable::REALTIME_CLOCK: { 56 | if (payload.toInt() > 0) { 57 | debugPrintln("UPDATE CONTROLLER DATETIME"); 58 | if (Datetime::getMyNowTm() != nullptr) { 59 | Controller::getInstance().getSolarController()->syncRealtimeClock(Datetime::getMyNowTm()); 60 | } 61 | } 62 | } break; 63 | case Variable::UPDATE_ALL_CONTROLLER_DATA: { 64 | if (payload.toInt() > 0) { 65 | debugPrintln("REQUEST ALL VALUES TO CONTROLLER"); 66 | Controller::getInstance().getSolarController()->fetchAllValues(); 67 | MqttSync::getInstance().uploadRealtimeToMqtt(); 68 | MqttSync::getInstance().uploadStatsToMqtt(); 69 | } 70 | } break; 71 | } 72 | } else { 73 | switch (def->datatype) { 74 | case VariableDatatype::DT_UINT16: { 75 | uint16_t newState = payload.toInt(); 76 | MqttSync::getInstance().applyUpdateToVariable(def->variable, &newState, false); 77 | } 78 | case VariableDatatype::DT_FLOAT: { 79 | float newState = payload.toFloat(); 80 | MqttSync::getInstance().applyUpdateToVariable(def->variable, &newState, false); 81 | } 82 | case VariableDatatype::DT_BOOL: { 83 | bool newState = payload.toInt() > 0; 84 | MqttSync::getInstance().applyUpdateToVariable(def->variable, &newState, false); 85 | } break; 86 | } 87 | } 88 | } 89 | } 90 | 91 | MqttSync::MqttSync() { 92 | WiFiClient *espClient = new WiFiClient(); 93 | this->mqttClient = new PubSubClient(*espClient); 94 | } 95 | 96 | void MqttSync::setup() { 97 | this->mqttClient->setServer(Environment::getData()->mqttServerHostname, Environment::getData()->mqttServerPort); 98 | 99 | mqttClient->setCallback(mqttCallback); 100 | for (uint8_t index = 0; index < Variable::VARIABLES_COUNT; index++) { 101 | const VariableDefinition *def = VariableDefiner::getInstance().getDefinition((Variable)index); 102 | if (def->mqttTopic != nullptr && def->mode == MD_READWRITE && (def->source == VariableSource::SR_INTERNAL || Controller::getInstance().getSolarController()->isVariableEnabled(def->variable))) { 103 | this->mqttClient->subscribe(def->mqttTopic); 104 | } 105 | } 106 | 107 | this->connect(); 108 | } 109 | 110 | void MqttSync::connect(bool blocking) { 111 | debugPrintf(true, Text::setupWithName, "MQTT"); 112 | debugPrint(Text::connecting); 113 | 114 | uint8_t counter = 0; 115 | 116 | do { 117 | mqttClient->connect( 118 | 119 | Environment::getData()->mqttClientId, 120 | strlen(Environment::getData()->mqttUsername) > 0 ? Environment::getData()->mqttUsername : nullptr, 121 | strlen(Environment::getData()->mqttPassword) > 0 ? Environment::getData()->mqttPassword : nullptr); 122 | while (!mqttClient->connected() && counter < 10) { 123 | debugPrint(Text::dot); 124 | delay(500); 125 | counter++; 126 | } 127 | 128 | if (mqttClient->state() != MQTT_CONNECTED) { 129 | debugPrintf(true, Text::errorWithCode, mqttClient->state()); 130 | } else { 131 | debugPrintln(Text::ok); 132 | } 133 | 134 | } while (blocking && !mqttClient->connected()); 135 | 136 | Controller::getInstance().setErrorFlag(STATUS_ERR_NO_MQTT_CONNECTION, !mqttClient->connected()); 137 | } 138 | void MqttSync::loop() { 139 | Controller::getInstance().setErrorFlag(STATUS_ERR_NO_MQTT_CONNECTION, !mqttClient->connected()); 140 | mqttClient->loop(); 141 | } 142 | bool MqttSync::isVariableAllowed(const VariableDefinition *def) { 143 | return def->mqttTopic != nullptr; 144 | } 145 | bool MqttSync::sendUpdateToVariable(const VariableDefinition *def, const void *value) { 146 | switch (def->datatype) { 147 | case VariableDatatype::DT_UINT16: 148 | #ifdef USE_MQTT_JSON_PUBLISH 149 | syncJson[def->mqttTopic] = *(uint16_t *)value; 150 | return true; 151 | #else 152 | dtostrf(*(uint16_t *)value, 0, 0, mqttPublishBuffer); 153 | #endif 154 | case VariableDatatype::DT_FLOAT: 155 | #ifdef USE_MQTT_JSON_PUBLISH 156 | syncJson[def->mqttTopic] = *(float *)value; 157 | return true; 158 | #else 159 | dtostrf(*(float *)value, 0, 4, mqttPublishBuffer); 160 | return mqttClient->publish(def->mqttTopic, mqttPublishBuffer, RETAIN_ALL_MSG); 161 | #endif 162 | case VariableDatatype::DT_BOOL: 163 | #ifdef USE_MQTT_JSON_PUBLISH 164 | syncJson[def->mqttTopic] = *(bool *)value; 165 | return true; 166 | #else 167 | return mqttClient->publish(def->mqttTopic, (*(const bool *)value) ? "1" : "0", RETAIN_ALL_MSG); 168 | #endif 169 | case VariableDatatype::DT_STRING: 170 | #ifdef USE_MQTT_JSON_PUBLISH 171 | syncJson[def->mqttTopic] = *(const char *)value; 172 | return true; 173 | #else 174 | return mqttClient->publish(def->mqttTopic, (const char *)value, RETAIN_ALL_MSG); 175 | #endif 176 | } 177 | return false; 178 | } 179 | 180 | // upload values stats 181 | void MqttSync::uploadStatsToMqtt() { 182 | if (!this->mqttClient->connected()) { 183 | return; 184 | } 185 | 186 | MqttSync::getInstance().sendUpdateAllBySource(VariableSource::SR_STATS, false); 187 | #ifdef USE_MQTT_JSON_PUBLISH 188 | String output; 189 | serializeJson(syncJson, output); 190 | if (syncJson.size() > 0) { 191 | mqttClient->publish(MQTT_JSON_PUBLISH_TOPIC, output.c_str()); 192 | } 193 | #endif 194 | } 195 | 196 | // upload values realtime 197 | void MqttSync::uploadRealtimeToMqtt() { 198 | if (!this->mqttClient->connected()) { 199 | return; 200 | } 201 | 202 | #ifdef MQTT_TOPIC_INTERNAL_STATUS 203 | float status = Controller::getInstance().getStatus(); 204 | this->sendUpdateToVariable(VariableDefiner::getInstance().getDefinition(Variable::INTERNAL_STATUS), &(status)); 205 | #endif 206 | this->sendUpdateAllBySource(VariableSource::SR_REALTIME, false); 207 | #ifdef USE_MQTT_JSON_PUBLISH 208 | String output; 209 | serializeJson(syncJson, output); 210 | if (syncJson.size() > 0) { 211 | mqttClient->publish(MQTT_JSON_PUBLISH_TOPIC, output.c_str()); 212 | } 213 | #endif 214 | } 215 | 216 | #endif 217 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/feature/MqttSync.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #include "../incl/include_all_core.h" 25 | 26 | #if defined(USE_MQTT) && !defined(USE_MQTT_HOME_ASSISTANT) 27 | 28 | #include "../core/BaseSync.h" 29 | #include "../core/Controller.h" 30 | #include "../core/VariableDefiner.h" 31 | #include "../incl/include_all_lib.h" 32 | 33 | class MqttSync : public BaseSync { 34 | public: 35 | static MqttSync &getInstance() { 36 | static MqttSync instance; 37 | return instance; 38 | } 39 | 40 | void setup(); 41 | void connect(bool blocking = true); 42 | void loop(); 43 | inline bool isVariableAllowed(const VariableDefinition *def); 44 | bool sendUpdateToVariable(const VariableDefinition *def, const void *value); 45 | // upload values stats 46 | void uploadStatsToMqtt(); 47 | // upload values realtime 48 | void uploadRealtimeToMqtt(); 49 | 50 | private: 51 | MqttSync(); 52 | 53 | PubSubClient *mqttClient; 54 | 55 | char mqttPublishBuffer[20]; 56 | 57 | #if defined(USE_MQTT_RPC_SUBSCRIBE) || defined(USE_MQTT_JSON_PUBLISH) 58 | DynamicJsonDocument syncJson(1024); 59 | #endif 60 | 61 | bool initialized; 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/feature/arduino_ota.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef ARDUINO_OTA_H 25 | #define ARDUINO_OTA_H 26 | 27 | #include "../incl/include_all_core.h" 28 | 29 | #ifdef USE_OTA_UPDATE 30 | 31 | #include "../core/Environment.h" 32 | #include "../incl/include_all_lib.h" 33 | 34 | inline void arduinoOtaSetup() { 35 | ArduinoOTA.setHostname(Environment::getData()->otaHostname); 36 | ArduinoOTA.setPassword(Environment::getData()->otaPassword); 37 | 38 | ArduinoOTA.onStart([]() { 39 | String type; 40 | if (ArduinoOTA.getCommand() == U_FLASH) { 41 | type = "sketch"; 42 | } else { // U_SPIFFS 43 | type = "filesystem"; 44 | } 45 | 46 | // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() 47 | debugPrintln("Start updating " + type); 48 | }); 49 | 50 | ArduinoOTA.onEnd([]() { debugPrintln("\nEnd of update"); }); 51 | 52 | ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { debugPrintf(false, "Progress: %u%%\r", (progress / (total / 100))); }); 53 | 54 | ArduinoOTA.onError([](ota_error_t error) { 55 | debugPrintf(false, "Error[%u]: ", error); 56 | if (error == OTA_AUTH_ERROR) { 57 | debugPrintln("Auth Failed"); 58 | } else if (error == OTA_BEGIN_ERROR) { 59 | debugPrintln("Begin Failed"); 60 | } else if (error == OTA_CONNECT_ERROR) { 61 | debugPrintln("Connect Failed"); 62 | } else if (error == OTA_RECEIVE_ERROR) { 63 | debugPrintln("Receive Failed"); 64 | } else if (error == OTA_END_ERROR) { 65 | debugPrintln("End Failed"); 66 | } 67 | }); 68 | 69 | ArduinoOTA.begin(); 70 | } 71 | 72 | #endif 73 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/feature/wifi_manager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef WIFI_MANAGER_H 25 | #define WIFI_MANAGER_H 26 | 27 | #include "../incl/include_all_core.h" 28 | 29 | #ifdef USE_WIFI_AP_CONFIGURATION 30 | 31 | #include "../core/Environment.h" 32 | #include "../incl/include_all_lib.h" 33 | 34 | class WifiManagerSTB { 35 | public: 36 | static void startWifiConfigurationAP(bool tryConnection) { 37 | bool shouldSaveConfig = false; 38 | 39 | // making sure to be connected to wifi from settings to get WiFi.SSID and WiFi.psk 40 | if (tryConnection) { 41 | WiFi.waitForConnectResult(); 42 | } 43 | 44 | WiFiManager wifiManager; 45 | wifiManager.setTitle("Solar-tracer-Blynk-V3"); 46 | wifiManager.setBreakAfterConfig(true); 47 | wifiManager.setSaveParamsCallback([&shouldSaveConfig, &wifiManager]() { 48 | shouldSaveConfig = true; 49 | wifiManager.stopConfigPortal(); }); 50 | wifiManager.setSaveConfigCallback([&shouldSaveConfig]() { shouldSaveConfig = true; }); 51 | wifiManager.setConfigResetCallback([]() { Environment::resetEnvData(); }); 52 | wifiManager.setParamsPage(true); 53 | wifiManager.setConfigPortalBlocking(true); 54 | wifiManager.setDebugOutput(false); 55 | 56 | WiFiManagerParameter customDebug( 57 | CONFIG_SERIAL_DEBUG, 58 | "Serial debug", 59 | CONFIG_SERIAL_DEBUG, 15, 60 | Environment::getData()->serialDebug ? "type=\"checkbox\" checked" : "type=\"checkbox\""); 61 | wifiManager.addParameter(&customDebug); 62 | 63 | WiFiManagerParameter customWIFIText("

WIFI:

"); 64 | wifiManager.addParameter(&customWIFIText); 65 | 66 | WiFiManagerParameter customWIFIIpAddress(CONFIG_WIFI_IP_ADDRESS, "IP", Environment::getData()->wifiIp, CONFIG_WIFI_IP_ADDRESS_LEN); 67 | wifiManager.addParameter(&customWIFIIpAddress); 68 | WiFiManagerParameter customWIFIGateway(CONFIG_WIFI_GATEWAY, "Gateway", Environment::getData()->wifiGateway, CONFIG_WIFI_GATEWAY_LEN); 69 | wifiManager.addParameter(&customWIFIGateway); 70 | WiFiManagerParameter customWIFISubnet(CONFIG_WIFI_SUBNET, "Subnet", Environment::getData()->wifiSubnet, CONFIG_WIFI_SUBNET_LEN); 71 | wifiManager.addParameter(&customWIFISubnet); 72 | WiFiManagerParameter customWIFIDns1(CONFIG_WIFI_DNS1, "Dns1", Environment::getData()->wifiDns1, CONFIG_WIFI_DNS1_LEN); 73 | wifiManager.addParameter(&customWIFIDns1); 74 | WiFiManagerParameter customWIFIDns2(CONFIG_WIFI_DNS2, "Dns2", Environment::getData()->wifiDns2, CONFIG_WIFI_DNS2_LEN); 75 | wifiManager.addParameter(&customWIFIDns2); 76 | 77 | #ifdef USE_BLYNK 78 | WiFiManagerParameter customBlynkText("

BLYNK:

"); 79 | wifiManager.addParameter(&customBlynkText); 80 | 81 | WiFiManagerParameter customBlynkAuth(CONFIG_BLYNK_AUTH, "API key", Environment::getData()->blynkAuth, CONFIG_BLYNK_AUTH_LEN); 82 | wifiManager.addParameter(&customBlynkAuth); 83 | 84 | #ifndef USE_BLYNK_2 85 | 86 | WiFiManagerParameter customBlynkServerHostname(CONFIG_BLYNK_HOSTNAME, Text::server, Environment::getData()->blynkServerHostname, CONFIG_BLYNK_HOSTNAME_LEN); 87 | WiFiManagerParameter customBlynkServerPort(CONFIG_BLYNK_PORT, Text::port, Util::intToChar(Environment::getData()->blynkServerPort), 5, "type=\"number\" min=\"0\""); 88 | 89 | wifiManager.addParameter(&customBlynkServerHostname); 90 | wifiManager.addParameter(&customBlynkServerPort); 91 | #endif 92 | #endif 93 | 94 | #ifdef USE_MQTT 95 | WiFiManagerParameter customMqttText("

MQTT:

"); 96 | wifiManager.addParameter(&customMqttText); 97 | 98 | WiFiManagerParameter customMqttServer(CONFIG_MQTT_HOSTNAME, Text::server, Environment::getData()->mqttServerHostname, CONFIG_MQTT_HOSTNAME_LEN); 99 | wifiManager.addParameter(&customMqttServer); 100 | char portString[5]; 101 | WiFiManagerParameter customMqttServerPort(CONFIG_MQTT_PORT, Text::port, Util::intToChar(Environment::getData()->mqttServerPort), 5, "type=\"number\" min=\"0\""); 102 | wifiManager.addParameter(&customMqttServerPort); 103 | WiFiManagerParameter customMqttClientId(CONFIG_MQTT_CLIENT_ID, "Client ID", Environment::getData()->mqttClientId, CONFIG_MQTT_CLIENT_ID_LEN); 104 | wifiManager.addParameter(&customMqttClientId); 105 | WiFiManagerParameter customMqttUsername(CONFIG_MQTT_USERNAME, "Username", Environment::getData()->mqttUsername, CONFIG_MQTT_USERNAME_LEN); 106 | wifiManager.addParameter(&customMqttUsername); 107 | WiFiManagerParameter customMqttPassword(CONFIG_MQTT_PASSWORD, Text::password, Environment::getData()->mqttPassword, CONFIG_MQTT_PASSWORD_LEN); 108 | wifiManager.addParameter(&customMqttPassword); 109 | #endif 110 | #ifdef USE_MQTT_HOME_ASSISTANT 111 | WiFiManagerParameter customMqttHAText("

MQTT-HA:

"); 112 | wifiManager.addParameter(&customMqttHAText); 113 | 114 | WiFiManagerParameter customMqttHADeviceId(CONFIG_MQTT_HA_DEVICE_ID, "Device ID", Environment::getData()->mqttHADeviceId, CONFIG_MQTT_HA_DEVICE_ID_LEN); 115 | wifiManager.addParameter(&customMqttHADeviceId); 116 | 117 | WiFiManagerParameter customMqttHADeviceName(CONFIG_MQTT_HA_DEVICE_NAME, "Device Name", Environment::getData()->mqttHADeviceName, CONFIG_MQTT_HA_DEVICE_NAME_LEN); 118 | wifiManager.addParameter(&customMqttHADeviceName); 119 | #endif 120 | 121 | #ifdef USE_OTA_UPDATE 122 | WiFiManagerParameter customOtaUpdateText("

OTA:

"); 123 | 124 | WiFiManagerParameter customOtaHostname(CONFIG_OTA_HOSTNAME, "Hostname", Environment::getData()->otaHostname, CONFIG_OTA_HOSTNAME_LEN); 125 | WiFiManagerParameter customOtaPassword(CONFIG_OTA_PASSWORD, Text::password, Environment::getData()->otaPassword, CONFIG_OTA_PASSWORD_LEN); 126 | 127 | wifiManager.addParameter(&customOtaUpdateText); 128 | wifiManager.addParameter(&customOtaHostname); 129 | wifiManager.addParameter(&customOtaPassword); 130 | #endif 131 | 132 | #ifdef USE_NTP_SERVER 133 | WiFiManagerParameter customNtpText("

NTP:

"); 134 | 135 | WiFiManagerParameter customNtpServer(CONFIG_NTP_SERVER, Text::server, Environment::getData()->ntpServer, CONFIG_NTP_SERVER_LEN); 136 | WiFiManagerParameter customNtpTimezone(CONFIG_NTP_TIMEZONE, "Timezone", Environment::getData()->ntpTimezone, CONFIG_NTP_TIMEZONE_LEN); 137 | 138 | wifiManager.addParameter(&customNtpText); 139 | wifiManager.addParameter(&customNtpServer); 140 | wifiManager.addParameter(&customNtpTimezone); 141 | #endif 142 | #ifdef USE_EXTERNAL_HEAVY_LOAD_CURRENT_METER 143 | WiFiManagerParameter customExtLoadMeter("

EXT. LOAD METER:

"); 144 | 145 | char hlVoltOffsetString[8]; 146 | WiFiManagerParameter customExtZeroVOff(CONFIG_EXTERNAL_HEAVY_LOAD_CURRENT_METER_VOLTAGE_ZERO_AMP_VOLT, "Volt off.", Util::floatToChar(Environment::getData()->heavyLoadCurrentZeroV), 8, "type=\"number\" step=\"0.001\""); 147 | 148 | wifiManager.addParameter(&customExtLoadMeter); 149 | wifiManager.addParameter(&customExtZeroVOff); 150 | #endif 151 | 152 | WiFiManagerParameter customWmText("

ACCESS POINT:

"); 153 | WiFiManagerParameter customWmSSID(CONFIG_WM_AP_SSID, "SSID", Environment::getData()->wmApSSID, CONFIG_WM_AP_SSID_LEN); 154 | WiFiManagerParameter customWmPassword(CONFIG_WM_AP_PASSWORD, Text::password, Environment::getData()->wmApPassword, CONFIG_WM_AP_PASSWORD_LEN); 155 | 156 | wifiManager.addParameter(&customWmText); 157 | wifiManager.addParameter(&customWmSSID); 158 | wifiManager.addParameter(&customWmPassword); 159 | 160 | wifiManager.setConfigPortalTimeout(WIFI_AP_TIMEOUT); 161 | wifiManager.startConfigPortal(Environment::getData()->wmApSSID, Environment::getData()->wmApPassword); 162 | 163 | if (shouldSaveConfig) { 164 | debugPrintln("Saving wifimanager parameters... "); 165 | 166 | if (!LittleFS.begin()) { 167 | debugPrintf(true, Text::errorWithCode, STATUS_ERR_LITTLEFS_BEGIN_FAILED); 168 | if (!LittleFS.format() || !LittleFS.begin()) { 169 | debugPrintf(true, Text::errorWithCode, STATUS_ERR_LITTLEFS_FORMAT_FAILED); 170 | } 171 | return; 172 | } 173 | 174 | DynamicJsonDocument doc(1024); 175 | doc[CONFIG_SERIAL_DEBUG] = strcmp(customDebug.getValue(), CONFIG_SERIAL_DEBUG) == 0; 176 | doc[CONFIG_WIFI_SSID] = WiFi.SSID(); 177 | doc[CONFIG_WIFI_PASSWORD] = WiFi.psk(); 178 | 179 | doc[CONFIG_WIFI_IP_ADDRESS] = customWIFIIpAddress.getValue(); 180 | doc[CONFIG_WIFI_GATEWAY] = customWIFIGateway.getValue(); 181 | doc[CONFIG_WIFI_SUBNET] = customWIFISubnet.getValue(); 182 | doc[CONFIG_WIFI_DNS1] = customWIFIDns1.getValue(); 183 | doc[CONFIG_WIFI_DNS2] = customWIFIDns2.getValue(); 184 | 185 | doc[CONFIG_WM_AP_SSID] = customWmSSID.getValue(); 186 | doc[CONFIG_WM_AP_PASSWORD] = customWmPassword.getValue(); 187 | #ifdef USE_BLYNK 188 | doc[CONFIG_BLYNK_AUTH] = customBlynkAuth.getValue(); 189 | #ifndef USE_BLYNK_2 190 | doc[CONFIG_BLYNK_HOSTNAME] = customBlynkServerHostname.getValue(); 191 | doc[CONFIG_BLYNK_PORT] = strlen(customBlynkServerPort.getValue()) > 0 192 | ? atoi(customBlynkServerPort.getValue()) 193 | : 0; 194 | #endif 195 | #endif 196 | #ifdef USE_MQTT 197 | doc[CONFIG_MQTT_HOSTNAME] = customMqttServer.getValue(); 198 | doc[CONFIG_MQTT_PORT] = strlen(customMqttServerPort.getValue()) > 0 199 | ? atoi(customMqttServerPort.getValue()) 200 | : 0; 201 | doc[CONFIG_MQTT_USERNAME] = customMqttUsername.getValue(); 202 | doc[CONFIG_MQTT_PASSWORD] = customMqttPassword.getValue(); 203 | doc[CONFIG_MQTT_CLIENT_ID] = customMqttClientId.getValue(); 204 | #endif 205 | #ifdef USE_MQTT_HOME_ASSISTANT 206 | doc[CONFIG_MQTT_HA_DEVICE_ID] = customMqttHADeviceId.getValue(); 207 | doc[CONFIG_MQTT_HA_DEVICE_NAME] = customMqttHADeviceName.getValue(); 208 | #endif 209 | 210 | #ifdef USE_OTA_UPDATE 211 | doc[CONFIG_OTA_HOSTNAME] = customOtaHostname.getValue(); 212 | doc[CONFIG_OTA_PASSWORD] = customOtaPassword.getValue(); 213 | #endif 214 | 215 | #ifdef USE_NTP_SERVER 216 | doc[CONFIG_NTP_SERVER] = customNtpServer.getValue(); 217 | doc[CONFIG_NTP_TIMEZONE] = customNtpTimezone.getValue(); 218 | #endif 219 | #ifdef USE_EXTERNAL_HEAVY_LOAD_CURRENT_METER 220 | doc[CONFIG_EXTERNAL_HEAVY_LOAD_CURRENT_METER_VOLTAGE_ZERO_AMP_VOLT] = strlen(customExtZeroVOff.getValue()) > 0 221 | ? atof(customExtZeroVOff.getValue()) 222 | : 0; 223 | #endif 224 | File configFile = LittleFS.open(CONFIG_PERSISTENCE, "w"); 225 | if (!configFile) { 226 | LittleFS.end(); 227 | } else { 228 | serializeJson(doc, configFile); 229 | configFile.flush(); 230 | configFile.close(); 231 | LittleFS.end(); 232 | debugPrintln(Text::ok); 233 | } 234 | 235 | ESP.restart(); 236 | } 237 | } 238 | }; 239 | 240 | #endif 241 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/incl/communication_protocol_all.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #define COMMUNICATION_PROTOCOL_MODBUS_RTU 0x00001 -------------------------------------------------------------------------------- /SolarTracerBlynk/src/incl/config_persistence.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #define CONFIG_PERSISTENCE "/config.json" 25 | 26 | //settings 27 | #define CONFIG_SERIAL_DEBUG "debug" 28 | 29 | #define CONFIG_WIFI_SSID "ssid" 30 | #define CONFIG_WIFI_SSID_LEN 20 31 | 32 | #define CONFIG_WIFI_PASSWORD "passw" 33 | #define CONFIG_WIFI_PASSWORD_LEN 30 34 | 35 | #define CONFIG_WM_AP_SSID "wmSsid" 36 | #define CONFIG_WM_AP_SSID_LEN 15 37 | 38 | #define CONFIG_WM_AP_PASSWORD "wmPassw" 39 | #define CONFIG_WM_AP_PASSWORD_LEN 30 40 | 41 | #define CONFIG_BLYNK_AUTH "blynkToken" 42 | #define CONFIG_BLYNK_AUTH_LEN 32 43 | 44 | #define CONFIG_BLYNK_HOSTNAME "blynkHostname" 45 | #define CONFIG_BLYNK_HOSTNAME_LEN 20 46 | 47 | #define CONFIG_BLYNK_PORT "blynkPort" 48 | 49 | #define CONFIG_MQTT_HOSTNAME "mqttSrv" 50 | #define CONFIG_MQTT_HOSTNAME_LEN 20 51 | 52 | #define CONFIG_MQTT_PORT "mqttPort" 53 | 54 | #define CONFIG_MQTT_CLIENT_ID "mqttClnt" 55 | #define CONFIG_MQTT_CLIENT_ID_LEN 15 56 | 57 | #define CONFIG_MQTT_USERNAME "mqttUsr" 58 | #define CONFIG_MQTT_USERNAME_LEN 15 59 | 60 | #define CONFIG_MQTT_PASSWORD "mqttPassw" 61 | #define CONFIG_MQTT_PASSWORD_LEN 64 62 | 63 | #define CONFIG_OTA_HOSTNAME "otaHostname" 64 | #define CONFIG_OTA_HOSTNAME_LEN 15 65 | 66 | #define CONFIG_MQTT_HA_DEVICE_ID "haDeviceId" 67 | #define CONFIG_MQTT_HA_DEVICE_ID_LEN 15 68 | 69 | #define CONFIG_MQTT_HA_DEVICE_NAME "haDeviceName" 70 | #define CONFIG_MQTT_HA_DEVICE_NAME_LEN 15 71 | 72 | #define CONFIG_OTA_PASSWORD "otaPassword" 73 | #define CONFIG_OTA_PASSWORD_LEN 15 74 | 75 | 76 | #define CONFIG_NTP_SERVER "ntpServer" 77 | #define CONFIG_NTP_SERVER_LEN 22 78 | 79 | #define CONFIG_NTP_TIMEZONE "ntpTimezone" 80 | #define CONFIG_NTP_TIMEZONE_LEN 47 81 | 82 | #define CONFIG_WIFI_IP_ADDRESS "ipAddr" 83 | #define CONFIG_WIFI_IP_ADDRESS_LEN 15 84 | 85 | #define CONFIG_WIFI_SUBNET "subnet" 86 | #define CONFIG_WIFI_SUBNET_LEN 15 87 | 88 | #define CONFIG_WIFI_GATEWAY "gateway" 89 | #define CONFIG_WIFI_GATEWAY_LEN 15 90 | 91 | #define CONFIG_WIFI_DNS1 "dns1" 92 | #define CONFIG_WIFI_DNS1_LEN 15 93 | 94 | #define CONFIG_WIFI_DNS2 "dns2" 95 | #define CONFIG_WIFI_DNS2_LEN 15 96 | 97 | #define CONFIG_EXTERNAL_HEAVY_LOAD_CURRENT_METER_VOLTAGE_ZERO_AMP_VOLT "hlZeroVOff" 98 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/incl/include.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | // INCL all core dependendecies 23 | #include "include_all_core.h" 24 | // INCL all third party libs 25 | #include "include_all_lib.h" 26 | // EXCEPTION: SoftwareSerial 27 | #ifdef USE_SOFTWARE_SERIAL 28 | SoftwareSerial softSerial; 29 | #define BOARD_ST_SERIAL_STREAM softSerial 30 | #endif 31 | 32 | // INCL main components 33 | #include "../core/datetime.h" 34 | #include "../core/Controller.h" 35 | // INCL optional features 36 | #include "include_all_feature.h" 37 | 38 | 39 | #if !defined(ESP8266) && !defined(ESP32) 40 | #error "Your board is not supported" 41 | #endif 42 | 43 | #if defined(USE_SOFTWARE_SERIAL) & !defined(BOARD_ST_SERIAL_PIN_MAPPING_RX) 44 | #error "USE_SOFTWARE_SERIAL requires BOARD_ST_SERIAL_PIN_MAPPING_RX" 45 | #endif 46 | 47 | #if defined(USE_SOFTWARE_SERIAL) & !defined(BOARD_ST_SERIAL_PIN_MAPPING_TX) 48 | #error "USE_SOFTWARE_SERIAL requires BOARD_ST_SERIAL_PIN_MAPPING_TX" 49 | #endif 50 | 51 | // DIRECTIVE VALIDATION FOR ESP8266 ONLY 52 | #ifdef ESP8266 53 | #if defined(USE_HALL_AP_CONFIGURATION_TRIGGER) 54 | #error "This board has no hall sensor to use! [ disable USE_HALL_AP_CONFIGURATION_TRIGGER ]" 55 | #endif 56 | 57 | #if !defined(USE_SOFTWARE_SERIAL) && ( defined(BOARD_ST_SERIAL_PIN_MAPPING_RX) | defined(BOARD_ST_SERIAL_PIN_MAPPING_TX) ) 58 | #error "This board does not support HW serial pin mapping! [ disable BOARD_ST_SERIAL_PIN_MAPPING_RX, BOARD_ST_SERIAL_PIN_MAPPING_TX ]" 59 | #endif 60 | #endif 61 | 62 | // DIRECTIVE VALIDATION FOR ESP32 ONLY 63 | #ifdef ESP32 64 | #ifdef USE_SOFTWARE_SERIAL 65 | #error "ESP32 does not need to use a sof. serial emulation [disable USE_SOFTWARE_SERIAL]" 66 | #endif 67 | #endif 68 | 69 | // DIRECTIVE VALIDATION FOR SOLAR TRACER 70 | #if !defined(USE_SERIAL_STREAM) && (SOLAR_TRACER_MODEL == EPEVER_SOLAR_TRACER_A | SOLAR_TRACER_MODEL == EPEVER_SOLAR_TRACER_B | SOLAR_TRACER_MODEL == EPEVER_SOLAR_TRACER_TRITON | SOLAR_TRACER_MODEL == EPEVER_SOLAR_TRACER_XTRA) 71 | #error You must enable USE_SERIAL_STREAM ! 72 | #endif 73 | 74 | #if defined(USE_SERIAL_STREAM) && !defined(BOARD_ST_SERIAL_STREAM) 75 | #error You must specify a serial in BOARD_ST_SERIAL_STREAM! 76 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/incl/include_all_blynk_vpin.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #include "../incl/include_all_core.h" 25 | 26 | /** 27 | * BLYNK 28 | * 29 | */ 30 | #ifndef vPIN_PV_POWER 31 | #define vPIN_PV_POWER_DF nullptr 32 | #else 33 | #define vPIN_PV_POWER_DF new uint8_t(vPIN_PV_POWER) 34 | #endif 35 | #ifndef vPIN_PV_CURRENT 36 | #define vPIN_PV_CURRENT_DF nullptr 37 | #else 38 | #define vPIN_PV_CURRENT_DF new uint8_t(vPIN_PV_CURRENT) 39 | #endif 40 | #ifndef vPIN_PV_VOLTAGE 41 | #define vPIN_PV_VOLTAGE_DF nullptr 42 | #else 43 | #define vPIN_PV_VOLTAGE_DF new uint8_t(vPIN_PV_VOLTAGE) 44 | #endif 45 | #ifndef vPIN_LOAD_CURRENT 46 | #define vPIN_LOAD_CURRENT_DF nullptr 47 | #else 48 | #define vPIN_LOAD_CURRENT_DF new uint8_t(vPIN_LOAD_CURRENT) 49 | #endif 50 | #ifndef vPIN_LOAD_POWER 51 | #define vPIN_LOAD_POWER_DF nullptr 52 | #else 53 | #define vPIN_LOAD_POWER_DF new uint8_t(vPIN_LOAD_POWER) 54 | #endif 55 | #ifndef vPIN_BATT_TEMP 56 | #define vPIN_BATT_TEMP_DF nullptr 57 | #else 58 | #define vPIN_BATT_TEMP_DF new uint8_t(vPIN_BATT_TEMP) 59 | #endif 60 | #ifndef vPIN_BATT_VOLTAGE 61 | #define vPIN_BATT_VOLTAGE_DF nullptr 62 | #else 63 | #define vPIN_BATT_VOLTAGE_DF new uint8_t(vPIN_BATT_VOLTAGE) 64 | #endif 65 | #ifndef vPIN_BATT_REMAIN 66 | #define vPIN_BATT_REMAIN_DF nullptr 67 | #else 68 | #define vPIN_BATT_REMAIN_DF new uint8_t(vPIN_BATT_REMAIN) 69 | #endif 70 | #ifndef vPIN_CONTROLLER_TEMP 71 | #define vPIN_CONTROLLER_TEMP_DF nullptr 72 | #else 73 | #define vPIN_CONTROLLER_TEMP_DF new uint8_t(vPIN_CONTROLLER_TEMP) 74 | #endif 75 | #ifndef vPIN_BATTERY_CHARGE_CURRENT 76 | #define vPIN_BATTERY_CHARGE_CURRENT_DF nullptr 77 | #else 78 | #define vPIN_BATTERY_CHARGE_CURRENT_DF new uint8_t(vPIN_BATTERY_CHARGE_CURRENT) 79 | #endif 80 | #ifndef vPIN_BATTERY_CHARGE_POWER 81 | #define vPIN_BATTERY_CHARGE_POWER_DF nullptr 82 | #else 83 | #define vPIN_BATTERY_CHARGE_POWER_DF new uint8_t(vPIN_BATTERY_CHARGE_POWER) 84 | #endif 85 | #ifndef vPIN_BATTERY_OVERALL_CURRENT 86 | #define vPIN_BATTERY_OVERALL_CURRENT_DF nullptr 87 | #else 88 | #define vPIN_BATTERY_OVERALL_CURRENT_DF new uint8_t(vPIN_BATTERY_OVERALL_CURRENT) 89 | #endif 90 | #ifndef vPIN_LOAD_ENABLED 91 | #define vPIN_LOAD_ENABLED_DF nullptr 92 | #else 93 | #define vPIN_LOAD_ENABLED_DF new uint8_t(vPIN_LOAD_ENABLED) 94 | #endif 95 | #ifndef vPIN_CHARGE_DEVICE_ENABLED 96 | #define vPIN_CHARGE_DEVICE_ENABLED_DF nullptr 97 | #else 98 | #define vPIN_CHARGE_DEVICE_ENABLED_DF new uint8_t(vPIN_CHARGE_DEVICE_ENABLED) 99 | #endif 100 | #ifndef vPIN_BATTERY_STATUS_TEXT 101 | #define vPIN_BATTERY_STATUS_TEXT_DF nullptr 102 | #else 103 | #define vPIN_BATTERY_STATUS_TEXT_DF new uint8_t(vPIN_BATTERY_STATUS_TEXT) 104 | #endif 105 | #ifndef vPIN_CHARGING_EQUIPMENT_STATUS_TEXT 106 | #define vPIN_CHARGING_EQUIPMENT_STATUS_TEXT_DF nullptr 107 | #else 108 | #define vPIN_CHARGING_EQUIPMENT_STATUS_TEXT_DF new uint8_t(vPIN_CHARGING_EQUIPMENT_STATUS_TEXT) 109 | #endif 110 | #ifndef vPIN_DISCHARGING_EQUIPMENT_STATUS_TEXT 111 | #define vPIN_DISCHARGING_EQUIPMENT_STATUS_TEXT_DF nullptr 112 | #else 113 | #define vPIN_DISCHARGING_EQUIPMENT_STATUS_TEXT_DF new uint8_t(vPIN_DISCHARGING_EQUIPMENT_STATUS_TEXT) 114 | #endif 115 | #ifndef vPIN_CONTROLLER_HEATSINK_TEMP 116 | #define vPIN_CONTROLLER_HEATSINK_TEMP_DF nullptr 117 | #else 118 | #define vPIN_CONTROLLER_HEATSINK_TEMP_DF new uint8_t(vPIN_CONTROLLER_HEATSINK_TEMP) 119 | #endif 120 | #ifndef vPIN_STAT_ENERGY_GENERATED_TODAY 121 | #define vPIN_STAT_ENERGY_GENERATED_TODAY_DF nullptr 122 | #else 123 | #define vPIN_STAT_ENERGY_GENERATED_TODAY_DF new uint8_t(vPIN_STAT_ENERGY_GENERATED_TODAY) 124 | #endif 125 | #ifndef vPIN_STAT_ENERGY_GENERATED_THIS_MONTH 126 | #define vPIN_STAT_ENERGY_GENERATED_THIS_MONTH_DF nullptr 127 | #else 128 | #define vPIN_STAT_ENERGY_GENERATED_THIS_MONTH_DF new uint8_t(vPIN_STAT_ENERGY_GENERATED_THIS_MONTH) 129 | #endif 130 | #ifndef vPIN_STAT_ENERGY_GENERATED_THIS_YEAR 131 | #define vPIN_STAT_ENERGY_GENERATED_THIS_YEAR_DF nullptr 132 | #else 133 | #define vPIN_STAT_ENERGY_GENERATED_THIS_YEAR_DF new uint8_t(vPIN_STAT_ENERGY_GENERATED_THIS_YEAR) 134 | #endif 135 | #ifndef vPIN_STAT_ENERGY_GENERATED_TOTAL 136 | #define vPIN_STAT_ENERGY_GENERATED_TOTAL_DF nullptr 137 | #else 138 | #define vPIN_STAT_ENERGY_GENERATED_TOTAL_DF new uint8_t(vPIN_STAT_ENERGY_GENERATED_TOTAL) 139 | #endif 140 | #ifndef vPIN_MIN_BATTERY_VOLTAGE_TODAY 141 | #define vPIN_MIN_BATTERY_VOLTAGE_TODAY_DF nullptr 142 | #else 143 | #define vPIN_MIN_BATTERY_VOLTAGE_TODAY_DF new uint8_t(vPIN_MIN_BATTERY_VOLTAGE_TODAY) 144 | #endif 145 | #ifndef vPIN_MAX_BATTERY_VOLTAGE_TODAY 146 | #define vPIN_MAX_BATTERY_VOLTAGE_TODAY_DF nullptr 147 | #else 148 | #define vPIN_MAX_BATTERY_VOLTAGE_TODAY_DF new uint8_t(vPIN_MAX_BATTERY_VOLTAGE_TODAY) 149 | #endif 150 | #ifndef vPIN_MIN_PV_VOLTAGE_TODAY 151 | #define vPIN_MIN_PV_VOLTAGE_TODAY_DF nullptr 152 | #else 153 | #define vPIN_MIN_PV_VOLTAGE_TODAY_DF new uint8_t(vPIN_MIN_PV_VOLTAGE_TODAY) 154 | #endif 155 | #ifndef vPIN_MAX_PV_VOLTAGE_TODAY 156 | #define vPIN_MAX_PV_VOLTAGE_TODAY_DF nullptr 157 | #else 158 | #define vPIN_MAX_PV_VOLTAGE_TODAY_DF new uint8_t(vPIN_MAX_PV_VOLTAGE_TODAY) 159 | #endif 160 | #ifndef vPIN_BATTERY_BOOST_VOLTAGE 161 | #define vPIN_BATTERY_BOOST_VOLTAGE_DF nullptr 162 | #else 163 | #define vPIN_BATTERY_BOOST_VOLTAGE_DF new uint8_t(vPIN_BATTERY_BOOST_VOLTAGE) 164 | #endif 165 | #ifndef vPIN_BATTERY_EQUALIZATION_VOLTAGE 166 | #define vPIN_BATTERY_EQUALIZATION_VOLTAGE_DF nullptr 167 | #else 168 | #define vPIN_BATTERY_EQUALIZATION_VOLTAGE_DF new uint8_t(vPIN_BATTERY_EQUALIZATION_VOLTAGE) 169 | #endif 170 | #ifndef vPIN_BATTERY_FLOAT_VOLTAGE 171 | #define vPIN_BATTERY_FLOAT_VOLTAGE_DF nullptr 172 | #else 173 | #define vPIN_BATTERY_FLOAT_VOLTAGE_DF new uint8_t(vPIN_BATTERY_FLOAT_VOLTAGE) 174 | #endif 175 | #ifndef vPIN_BATTERY_FLOAT_MIN_VOLTAGE 176 | #define vPIN_BATTERY_FLOAT_MIN_VOLTAGE_DF nullptr 177 | #else 178 | #define vPIN_BATTERY_FLOAT_MIN_VOLTAGE_DF new uint8_t(vPIN_BATTERY_FLOAT_MIN_VOLTAGE) 179 | #endif 180 | #ifndef vPIN_BATTERY_CHARGING_LIMIT_VOLTAGE 181 | #define vPIN_BATTERY_CHARGING_LIMIT_VOLTAGE_DF nullptr 182 | #else 183 | #define vPIN_BATTERY_CHARGING_LIMIT_VOLTAGE_DF new uint8_t(vPIN_BATTERY_CHARGING_LIMIT_VOLTAGE) 184 | #endif 185 | #ifndef vPIN_BATTERY_DISCHARGING_LIMIT_VOLTAGE 186 | #define vPIN_BATTERY_DISCHARGING_LIMIT_VOLTAGE_DF nullptr 187 | #else 188 | #define vPIN_BATTERY_DISCHARGING_LIMIT_VOLTAGE_DF new uint8_t(vPIN_BATTERY_DISCHARGING_LIMIT_VOLTAGE) 189 | #endif 190 | #ifndef vPIN_BATTERY_LOW_VOLTAGE_DISCONNECT 191 | #define vPIN_BATTERY_LOW_VOLTAGE_DISCONNECT_DF nullptr 192 | #else 193 | #define vPIN_BATTERY_LOW_VOLTAGE_DISCONNECT_DF new uint8_t(vPIN_BATTERY_LOW_VOLTAGE_DISCONNECT) 194 | #endif 195 | #ifndef vPIN_BATTERY_LOW_VOLTAGE_RECONNECT 196 | #define vPIN_BATTERY_LOW_VOLTAGE_RECONNECT_DF nullptr 197 | #else 198 | #define vPIN_BATTERY_LOW_VOLTAGE_RECONNECT_DF new uint8_t(vPIN_BATTERY_LOW_VOLTAGE_RECONNECT) 199 | #endif 200 | #ifndef vPIN_BATTERY_OVER_VOLTAGE_DISCONNECT 201 | #define vPIN_BATTERY_OVER_VOLTAGE_DISCONNECT_DF nullptr 202 | #else 203 | #define vPIN_BATTERY_OVER_VOLTAGE_DISCONNECT_DF new uint8_t(vPIN_BATTERY_OVER_VOLTAGE_DISCONNECT) 204 | #endif 205 | #ifndef vPIN_BATTERY_OVER_VOLTAGE_RECONNECT 206 | #define vPIN_BATTERY_OVER_VOLTAGE_RECONNECT_DF nullptr 207 | #else 208 | #define vPIN_BATTERY_OVER_VOLTAGE_RECONNECT_DF new uint8_t(vPIN_BATTERY_OVER_VOLTAGE_RECONNECT) 209 | #endif 210 | #ifndef vPIN_BATTERY_UNDER_VOLTAGE_RESET 211 | #define vPIN_BATTERY_UNDER_VOLTAGE_RESET_DF nullptr 212 | #else 213 | #define vPIN_BATTERY_UNDER_VOLTAGE_RESET_DF new uint8_t(vPIN_BATTERY_UNDER_VOLTAGE_RESET) 214 | #endif 215 | #ifndef vPIN_BATTERY_UNDER_VOLTAGE_SET 216 | #define vPIN_BATTERY_UNDER_VOLTAGE_SET_DF nullptr 217 | #else 218 | #define vPIN_BATTERY_UNDER_VOLTAGE_SET_DF new uint8_t(vPIN_BATTERY_UNDER_VOLTAGE_SET) 219 | #endif 220 | #ifndef vPIN_INTERNAL_STATUS 221 | #define vPIN_INTERNAL_STATUS_DF nullptr 222 | #else 223 | #define vPIN_INTERNAL_STATUS_DF new uint8_t(vPIN_INTERNAL_STATUS) 224 | #endif 225 | #ifndef vPIN_INTERNAL_DEBUG_TERMINAL 226 | #define vPIN_INTERNAL_DEBUG_TERMINAL_DF nullptr 227 | #else 228 | #define vPIN_INTERNAL_DEBUG_TERMINAL_DF new uint8_t(vPIN_INTERNAL_DEBUG_TERMINAL) 229 | #endif 230 | #ifndef vPIN_UPDATE_CONTROLLER_DATETIME 231 | #define vPIN_UPDATE_CONTROLLER_DATETIME_DF nullptr 232 | #else 233 | #define vPIN_UPDATE_CONTROLLER_DATETIME_DF new uint8_t(vPIN_UPDATE_CONTROLLER_DATETIME) 234 | #endif 235 | #ifndef vPIN_UPDATE_ALL_CONTROLLER_DATA 236 | #define vPIN_UPDATE_ALL_CONTROLLER_DATA_DF nullptr 237 | #else 238 | #define vPIN_UPDATE_ALL_CONTROLLER_DATA_DF new uint8_t(vPIN_UPDATE_ALL_CONTROLLER_DATA) 239 | #endif 240 | #ifndef vPIN_BATTERY_RATED_VOLTAGE 241 | #define vPIN_BATTERY_RATED_VOLTAGE_DF nullptr 242 | #else 243 | #define vPIN_BATTERY_RATED_VOLTAGE_DF new uint8_t(vPIN_BATTERY_RATED_VOLTAGE) 244 | #endif 245 | #ifndef vPIN_BATTERY_TYPE 246 | #define vPIN_BATTERY_TYPE_DF nullptr 247 | #else 248 | #define vPIN_BATTERY_TYPE_DF new uint8_t(vPIN_BATTERY_TYPE) 249 | #endif 250 | #ifndef vPIN_BATTERY_CAPACITY 251 | #define vPIN_BATTERY_CAPACITY_DF nullptr 252 | #else 253 | #define vPIN_BATTERY_CAPACITY_DF new uint8_t(vPIN_BATTERY_CAPACITY) 254 | #endif 255 | #ifndef vPIN_BATTERY_EQUALIZATION_DURATION 256 | #define vPIN_BATTERY_EQUALIZATION_DURATION_DF nullptr 257 | #else 258 | #define vPIN_BATTERY_EQUALIZATION_DURATION_DF new uint8_t(vPIN_BATTERY_EQUALIZATION_DURATION) 259 | #endif 260 | #ifndef vPIN_BATTERY_BOOST_DURATION 261 | #define vPIN_BATTERY_BOOST_DURATION_DF nullptr 262 | #else 263 | #define vPIN_BATTERY_BOOST_DURATION_DF new uint8_t(vPIN_BATTERY_BOOST_DURATION) 264 | #endif 265 | #ifndef vPIN_BATTERY_TEMPERATURE_COMPENSATION_COEFF 266 | #define vPIN_BATTERY_TEMPERATURE_COMPENSATION_COEFF_DF nullptr 267 | #else 268 | #define vPIN_BATTERY_TEMPERATURE_COMPENSATION_COEFF_DF new uint8_t(vPIN_BATTERY_TEMPERATURE_COMPENSATION_COEFF) 269 | #endif 270 | #ifndef vPIN_BATTERY_MANAGEMENT_MODE 271 | #define vPIN_BATTERY_MANAGEMENT_MODE_DF nullptr 272 | #else 273 | #define vPIN_BATTERY_MANAGEMENT_MODE_DF new uint8_t(vPIN_BATTERY_MANAGEMENT_MODE) 274 | #endif 275 | #ifndef vPIN_STAT_ENERGY_CONSUMED_TODAY 276 | #define vPIN_STAT_ENERGY_CONSUMED_TODAY_DF nullptr 277 | #else 278 | #define vPIN_STAT_ENERGY_CONSUMED_TODAY_DF new uint8_t(vPIN_STAT_ENERGY_CONSUMED_TODAY) 279 | #endif 280 | #ifndef vPIN_STAT_ENERGY_CONSUMED_THIS_MONTH 281 | #define vPIN_STAT_ENERGY_CONSUMED_THIS_MONTH_DF nullptr 282 | #else 283 | #define vPIN_STAT_ENERGY_CONSUMED_THIS_MONTH_DF new uint8_t(vPIN_STAT_ENERGY_CONSUMED_THIS_MONTH) 284 | #endif 285 | #ifndef vPIN_STAT_ENERGY_CONSUMED_THIS_YEAR 286 | #define vPIN_STAT_ENERGY_CONSUMED_THIS_YEAR_DF nullptr 287 | #else 288 | #define vPIN_STAT_ENERGY_CONSUMED_THIS_YEAR_DF new uint8_t(vPIN_STAT_ENERGY_CONSUMED_THIS_YEAR) 289 | #endif 290 | #ifndef vPIN_STAT_ENERGY_CONSUMED_TOTAL 291 | #define vPIN_STAT_ENERGY_CONSUMED_TOTAL_DF nullptr 292 | #else 293 | #define vPIN_STAT_ENERGY_CONSUMED_TOTAL_DF new uint8_t(vPIN_STAT_ENERGY_CONSUMED_TOTAL) 294 | #endif 295 | 296 | 297 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/incl/include_all_core.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef INCLUDE_ALL_CORE_H 25 | #define INCLUDE_ALL_CORE_H 26 | 27 | #define PROJECT_NAME "Solar-Tracer-Blynk-V3" 28 | #define PROJECT_AUTHOR "Bettapro" 29 | #define PROJECT_VERSION "v3.0.9" 30 | #define PROJECT_SUBVERSION 17 31 | 32 | 33 | #include 34 | 35 | /** 36 | * Main defs 37 | */ 38 | #include "solartracer_all.h" 39 | #include "communication_protocol_all.h" 40 | #include "status_all.h" 41 | #include "config_persistence.h" 42 | 43 | 44 | /** 45 | * Include user + board + solar tracer configs 46 | */ 47 | #include "../../config.h" 48 | 49 | // disable advanced features not needed in the startup build 50 | #ifdef STARTUP_BUILD 51 | #undef USE_BLYNK 52 | #undef USE_MQTT 53 | #undef USE_SERIAL_STREAM 54 | 55 | #undef SOLAR_TRACER_MODEL 56 | #define SOLAR_TRACER_MODEL DUMMY_SOLAR_TRACER 57 | #endif 58 | 59 | 60 | 61 | /** 62 | * Conditional includes depending on the BOARD 63 | */ 64 | #if defined ESP32 65 | #include "../board/esp32_config.h" 66 | #elif defined ESP8266 67 | #include "../board/esp8266_config.h" 68 | #else 69 | #error Your board is not supported. 70 | #endif 71 | 72 | /** 73 | * Conditional includes depending on the SOLAR CHARGE CONTROLLER 74 | */ 75 | #if (SOLAR_TRACER_MODEL == EPEVER_SOLAR_TRACER_A | SOLAR_TRACER_MODEL == EPEVER_SOLAR_TRACER_B | SOLAR_TRACER_MODEL == EPEVER_SOLAR_TRACER_TRITON | SOLAR_TRACER_MODEL == EPEVER_SOLAR_TRACER_XTRA) 76 | #include "../solartracer/epever/epever_config.h" 77 | #elif (SOLAR_TRACER_MODEL == DUMMY_SOLAR_TRACER) 78 | #else 79 | #error This Solar Tracer is not supported. 80 | #endif 81 | 82 | /** 83 | * Include only not-external-dependant headers 84 | */ 85 | #include "../core/Util.h" 86 | #include "../core/debug.h" 87 | #include "../core/Text.h" 88 | #include "../core/VariableDefiner.h" 89 | 90 | 91 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/incl/include_all_feature.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef INCLUDE_ALL_FEATURE_H 25 | #define INCLUDE_ALL_FEATURE_H 26 | 27 | #include "include_all_core.h" 28 | 29 | #ifdef USE_EXTERNAL_HEAVY_LOAD_CURRENT_METER 30 | #include "../solartracer/overwrite/LoadCurrentOverwrite.h" 31 | #endif 32 | 33 | #ifdef USE_STATUS_LED 34 | #include "../feature/status_led.h" 35 | #endif 36 | 37 | #ifdef USE_OTA_UPDATE 38 | #include "../feature/arduino_ota.h" 39 | #endif 40 | 41 | #if defined USE_WIFI_AP_CONFIGURATION 42 | #include "../feature/wifi_manager.h" 43 | #endif 44 | 45 | #if defined USE_BLYNK 46 | #include "../feature/BlynkSync.h" 47 | #endif 48 | #if defined(USE_MQTT) && !defined(USE_MQTT_HOME_ASSISTANT) 49 | #include "../feature/MqttSync.h" 50 | #endif 51 | #if defined(USE_MQTT) && defined(USE_MQTT_HOME_ASSISTANT) 52 | #include "../feature/MqttHASync.h" 53 | #endif 54 | 55 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/incl/include_all_lib.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef INCLUDE_ALL_LIB_H 25 | #define INCLUDE_ALL_LIB_H 26 | 27 | #include "include_all_core.h" 28 | 29 | #if defined ESP32 30 | #define USE_WIFI_NINA false 31 | #define USE_WIFI101 false 32 | #include 33 | #elif defined ESP8266 34 | #include 35 | #endif 36 | 37 | #ifdef USE_SOFTWARE_SERIAL 38 | #include 39 | #endif 40 | 41 | #include 42 | 43 | #ifdef USE_DOUBLE_RESET_TRIGGER 44 | #include 45 | #define ESP_DRD_USE_LITTLEFS true 46 | #include 47 | #endif 48 | 49 | #ifdef USE_OTA_UPDATE 50 | #include 51 | #endif 52 | 53 | #include 54 | #if defined USE_WIFI_AP_CONFIGURATION 55 | #include 56 | // disable WM all logs 57 | // #define WM_NODEBUG 58 | #include 59 | #endif 60 | 61 | #if defined(USE_MQTT) && !defined(USE_MQTT_HOME_ASSISTANT) 62 | #include 63 | #endif 64 | #if defined(USE_MQTT) && defined(USE_MQTT_HOME_ASSISTANT) 65 | #include 66 | #endif 67 | 68 | #ifdef USE_EXTERNAL_HEAVY_LOAD_CURRENT_METER 69 | #ifdef USE_EXTERNAL_HEAVY_LOAD_CURRENT_METER_ADS1015_ADC 70 | #include "ADS1X15.h" 71 | #endif 72 | #include 73 | #endif 74 | 75 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/incl/include_all_mqtt_topic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #include "../incl/include_all_core.h" 25 | 26 | 27 | /** 28 | * MQTT 29 | * 30 | */ 31 | 32 | 33 | #ifndef MQTT_TOPIC_PV_POWER 34 | #define MQTT_TOPIC_PV_POWER_DF nullptr 35 | #else 36 | #define MQTT_TOPIC_PV_POWER_DF MQTT_TOPIC_PV_POWER 37 | #endif 38 | #ifndef MQTT_TOPIC_PV_CURRENT 39 | #define MQTT_TOPIC_PV_CURRENT_DF nullptr 40 | #else 41 | #define MQTT_TOPIC_PV_CURRENT_DF MQTT_TOPIC_PV_CURRENT 42 | #endif 43 | #ifndef MQTT_TOPIC_PV_VOLTAGE 44 | #define MQTT_TOPIC_PV_VOLTAGE_DF nullptr 45 | #else 46 | #define MQTT_TOPIC_PV_VOLTAGE_DF MQTT_TOPIC_PV_VOLTAGE 47 | #endif 48 | #ifndef MQTT_TOPIC_LOAD_CURRENT 49 | #define MQTT_TOPIC_LOAD_CURRENT_DF nullptr 50 | #else 51 | #define MQTT_TOPIC_LOAD_CURRENT_DF MQTT_TOPIC_LOAD_CURRENT 52 | #endif 53 | #ifndef MQTT_TOPIC_LOAD_POWER 54 | #define MQTT_TOPIC_LOAD_POWER_DF nullptr 55 | #else 56 | #define MQTT_TOPIC_LOAD_POWER_DF MQTT_TOPIC_LOAD_POWER 57 | #endif 58 | #ifndef MQTT_TOPIC_BATT_TEMP 59 | #define MQTT_TOPIC_BATT_TEMP_DF nullptr 60 | #else 61 | #define MQTT_TOPIC_BATT_TEMP_DF MQTT_TOPIC_BATT_TEMP 62 | #endif 63 | #ifndef MQTT_TOPIC_BATT_VOLTAGE 64 | #define MQTT_TOPIC_BATT_VOLTAGE_DF nullptr 65 | #else 66 | #define MQTT_TOPIC_BATT_VOLTAGE_DF MQTT_TOPIC_BATT_VOLTAGE 67 | #endif 68 | #ifndef MQTT_TOPIC_BATT_REMAIN 69 | #define MQTT_TOPIC_BATT_REMAIN_DF nullptr 70 | #else 71 | #define MQTT_TOPIC_BATT_REMAIN_DF MQTT_TOPIC_BATT_REMAIN 72 | #endif 73 | #ifndef MQTT_TOPIC_CONTROLLER_TEMP 74 | #define MQTT_TOPIC_CONTROLLER_TEMP_DF nullptr 75 | #else 76 | #define MQTT_TOPIC_CONTROLLER_TEMP_DF MQTT_TOPIC_CONTROLLER_TEMP 77 | #endif 78 | #ifndef MQTT_TOPIC_BATTERY_CHARGE_CURRENT 79 | #define MQTT_TOPIC_BATTERY_CHARGE_CURRENT_DF nullptr 80 | #else 81 | #define MQTT_TOPIC_BATTERY_CHARGE_CURRENT_DF MQTT_TOPIC_BATTERY_CHARGE_CURRENT 82 | #endif 83 | #ifndef MQTT_TOPIC_BATTERY_CHARGE_POWER 84 | #define MQTT_TOPIC_BATTERY_CHARGE_POWER_DF nullptr 85 | #else 86 | #define MQTT_TOPIC_BATTERY_CHARGE_POWER_DF MQTT_TOPIC_BATTERY_CHARGE_POWER 87 | #endif 88 | #ifndef MQTT_TOPIC_BATTERY_OVERALL_CURRENT 89 | #define MQTT_TOPIC_BATTERY_OVERALL_CURRENT_DF nullptr 90 | #else 91 | #define MQTT_TOPIC_BATTERY_OVERALL_CURRENT_DF MQTT_TOPIC_BATTERY_OVERALL_CURRENT 92 | #endif 93 | #ifndef MQTT_TOPIC_LOAD_ENABLED 94 | #define MQTT_TOPIC_LOAD_ENABLED_DF nullptr 95 | #else 96 | #define MQTT_TOPIC_LOAD_ENABLED_DF MQTT_TOPIC_LOAD_ENABLED 97 | #endif 98 | #ifndef MQTT_TOPIC_CHARGE_DEVICE_ENABLED 99 | #define MQTT_TOPIC_CHARGE_DEVICE_ENABLED_DF nullptr 100 | #else 101 | #define MQTT_TOPIC_CHARGE_DEVICE_ENABLED_DF MQTT_TOPIC_CHARGE_DEVICE_ENABLED 102 | #endif 103 | #ifndef MQTT_TOPIC_BATTERY_STATUS_TEXT 104 | #define MQTT_TOPIC_BATTERY_STATUS_TEXT_DF nullptr 105 | #else 106 | #define MQTT_TOPIC_BATTERY_STATUS_TEXT_DF MQTT_TOPIC_BATTERY_STATUS_TEXT 107 | #endif 108 | #ifndef MQTT_TOPIC_CHARGING_EQUIPMENT_STATUS_TEXT 109 | #define MQTT_TOPIC_CHARGING_EQUIPMENT_STATUS_TEXT_DF nullptr 110 | #else 111 | #define MQTT_TOPIC_CHARGING_EQUIPMENT_STATUS_TEXT_DF MQTT_TOPIC_CHARGING_EQUIPMENT_STATUS_TEXT 112 | #endif 113 | #ifndef MQTT_TOPIC_DISCHARGING_EQUIPMENT_STATUS_TEXT 114 | #define MQTT_TOPIC_DISCHARGING_EQUIPMENT_STATUS_TEXT_DF nullptr 115 | #else 116 | #define MQTT_TOPIC_DISCHARGING_EQUIPMENT_STATUS_TEXT_DF MQTT_TOPIC_DISCHARGING_EQUIPMENT_STATUS_TEXT 117 | #endif 118 | #ifndef MQTT_TOPIC_CONTROLLER_HEATSINK_TEMP 119 | #define MQTT_TOPIC_CONTROLLER_HEATSINK_TEMP_DF nullptr 120 | #else 121 | #define MQTT_TOPIC_CONTROLLER_HEATSINK_TEMP_DF MQTT_TOPIC_CONTROLLER_HEATSINK_TEMP 122 | #endif 123 | #ifndef MQTT_TOPIC_STAT_ENERGY_GENERATED_TODAY 124 | #define MQTT_TOPIC_STAT_ENERGY_GENERATED_TODAY_DF nullptr 125 | #else 126 | #define MQTT_TOPIC_STAT_ENERGY_GENERATED_TODAY_DF MQTT_TOPIC_STAT_ENERGY_GENERATED_TODAY 127 | #endif 128 | #ifndef MQTT_TOPIC_STAT_ENERGY_GENERATED_THIS_MONTH 129 | #define MQTT_TOPIC_STAT_ENERGY_GENERATED_THIS_MONTH_DF nullptr 130 | #else 131 | #define MQTT_TOPIC_STAT_ENERGY_GENERATED_THIS_MONTH_DF MQTT_TOPIC_STAT_ENERGY_GENERATED_THIS_MONTH 132 | #endif 133 | #ifndef MQTT_TOPIC_STAT_ENERGY_GENERATED_THIS_YEAR 134 | #define MQTT_TOPIC_STAT_ENERGY_GENERATED_THIS_YEAR_DF nullptr 135 | #else 136 | #define MQTT_TOPIC_STAT_ENERGY_GENERATED_THIS_YEAR_DF MQTT_TOPIC_STAT_ENERGY_GENERATED_THIS_YEAR 137 | #endif 138 | #ifndef MQTT_TOPIC_STAT_ENERGY_GENERATED_TOTAL 139 | #define MQTT_TOPIC_STAT_ENERGY_GENERATED_TOTAL_DF nullptr 140 | #else 141 | #define MQTT_TOPIC_STAT_ENERGY_GENERATED_TOTAL_DF MQTT_TOPIC_STAT_ENERGY_GENERATED_TOTAL 142 | #endif 143 | #ifndef MQTT_TOPIC_MIN_BATTERY_VOLTAGE_TODAY 144 | #define MQTT_TOPIC_MIN_BATTERY_VOLTAGE_TODAY_DF nullptr 145 | #else 146 | #define MQTT_TOPIC_MIN_BATTERY_VOLTAGE_TODAY_DF MQTT_TOPIC_MIN_BATTERY_VOLTAGE_TODAY 147 | #endif 148 | #ifndef MQTT_TOPIC_MAX_BATTERY_VOLTAGE_TODAY 149 | #define MQTT_TOPIC_MAX_BATTERY_VOLTAGE_TODAY_DF nullptr 150 | #else 151 | #define MQTT_TOPIC_MAX_BATTERY_VOLTAGE_TODAY_DF MQTT_TOPIC_MAX_BATTERY_VOLTAGE_TODAY 152 | #endif 153 | #ifndef MQTT_TOPIC_MIN_PV_VOLTAGE_TODAY 154 | #define MQTT_TOPIC_MIN_PV_VOLTAGE_TODAY_DF nullptr 155 | #else 156 | #define MQTT_TOPIC_MIN_PV_VOLTAGE_TODAY_DF MQTT_TOPIC_MIN_PV_VOLTAGE_TODAY 157 | #endif 158 | #ifndef MQTT_TOPIC_MAX_PV_VOLTAGE_TODAY 159 | #define MQTT_TOPIC_MAX_PV_VOLTAGE_TODAY_DF nullptr 160 | #else 161 | #define MQTT_TOPIC_MAX_PV_VOLTAGE_TODAY_DF MQTT_TOPIC_MAX_PV_VOLTAGE_TODAY 162 | #endif 163 | #ifndef MQTT_TOPIC_BATTERY_BOOST_VOLTAGE 164 | #define MQTT_TOPIC_BATTERY_BOOST_VOLTAGE_DF nullptr 165 | #else 166 | #define MQTT_TOPIC_BATTERY_BOOST_VOLTAGE_DF MQTT_TOPIC_BATTERY_BOOST_VOLTAGE 167 | #endif 168 | #ifndef MQTT_TOPIC_BATTERY_EQUALIZATION_VOLTAGE 169 | #define MQTT_TOPIC_BATTERY_EQUALIZATION_VOLTAGE_DF nullptr 170 | #else 171 | #define MQTT_TOPIC_BATTERY_EQUALIZATION_VOLTAGE_DF MQTT_TOPIC_BATTERY_EQUALIZATION_VOLTAGE 172 | #endif 173 | #ifndef MQTT_TOPIC_BATTERY_FLOAT_VOLTAGE 174 | #define MQTT_TOPIC_BATTERY_FLOAT_VOLTAGE_DF nullptr 175 | #else 176 | #define MQTT_TOPIC_BATTERY_FLOAT_VOLTAGE_DF MQTT_TOPIC_BATTERY_FLOAT_VOLTAGE 177 | #endif 178 | #ifndef MQTT_TOPIC_BATTERY_FLOAT_MIN_VOLTAGE 179 | #define MQTT_TOPIC_BATTERY_FLOAT_MIN_VOLTAGE_DF nullptr 180 | #else 181 | #define MQTT_TOPIC_BATTERY_FLOAT_MIN_VOLTAGE_DF MQTT_TOPIC_BATTERY_FLOAT_MIN_VOLTAGE 182 | #endif 183 | #ifndef MQTT_TOPIC_BATTERY_CHARGING_LIMIT_VOLTAGE 184 | #define MQTT_TOPIC_BATTERY_CHARGING_LIMIT_VOLTAGE_DF nullptr 185 | #else 186 | #define MQTT_TOPIC_BATTERY_CHARGING_LIMIT_VOLTAGE_DF MQTT_TOPIC_BATTERY_CHARGING_LIMIT_VOLTAGE 187 | #endif 188 | #ifndef MQTT_TOPIC_BATTERY_DISCHARGING_LIMIT_VOLTAGE 189 | #define MQTT_TOPIC_BATTERY_DISCHARGING_LIMIT_VOLTAGE_DF nullptr 190 | #else 191 | #define MQTT_TOPIC_BATTERY_DISCHARGING_LIMIT_VOLTAGE_DF MQTT_TOPIC_BATTERY_DISCHARGING_LIMIT_VOLTAGE 192 | #endif 193 | #ifndef MQTT_TOPIC_BATTERY_LOW_VOLTAGE_DISCONNECT 194 | #define MQTT_TOPIC_BATTERY_LOW_VOLTAGE_DISCONNECT_DF nullptr 195 | #else 196 | #define MQTT_TOPIC_BATTERY_LOW_VOLTAGE_DISCONNECT_DF MQTT_TOPIC_BATTERY_LOW_VOLTAGE_DISCONNECT 197 | #endif 198 | #ifndef MQTT_TOPIC_BATTERY_LOW_VOLTAGE_RECONNECT 199 | #define MQTT_TOPIC_BATTERY_LOW_VOLTAGE_RECONNECT_DF nullptr 200 | #else 201 | #define MQTT_TOPIC_BATTERY_LOW_VOLTAGE_RECONNECT_DF MQTT_TOPIC_BATTERY_LOW_VOLTAGE_RECONNECT 202 | #endif 203 | #ifndef MQTT_TOPIC_BATTERY_OVER_VOLTAGE_DISCONNECT 204 | #define MQTT_TOPIC_BATTERY_OVER_VOLTAGE_DISCONNECT_DF nullptr 205 | #else 206 | #define MQTT_TOPIC_BATTERY_OVER_VOLTAGE_DISCONNECT_DF MQTT_TOPIC_BATTERY_OVER_VOLTAGE_DISCONNECT 207 | #endif 208 | #ifndef MQTT_TOPIC_BATTERY_OVER_VOLTAGE_RECONNECT 209 | #define MQTT_TOPIC_BATTERY_OVER_VOLTAGE_RECONNECT_DF nullptr 210 | #else 211 | #define MQTT_TOPIC_BATTERY_OVER_VOLTAGE_RECONNECT_DF MQTT_TOPIC_BATTERY_OVER_VOLTAGE_RECONNECT 212 | #endif 213 | #ifndef MQTT_TOPIC_BATTERY_UNDER_VOLTAGE_RESET 214 | #define MQTT_TOPIC_BATTERY_UNDER_VOLTAGE_RESET_DF nullptr 215 | #else 216 | #define MQTT_TOPIC_BATTERY_UNDER_VOLTAGE_RESET_DF MQTT_TOPIC_BATTERY_UNDER_VOLTAGE_RESET 217 | #endif 218 | #ifndef MQTT_TOPIC_BATTERY_UNDER_VOLTAGE_SET 219 | #define MQTT_TOPIC_BATTERY_UNDER_VOLTAGE_SET_DF nullptr 220 | #else 221 | #define MQTT_TOPIC_BATTERY_UNDER_VOLTAGE_SET_DF MQTT_TOPIC_BATTERY_UNDER_VOLTAGE_SET 222 | #endif 223 | #ifndef MQTT_TOPIC_INTERNAL_STATUS 224 | #define MQTT_TOPIC_INTERNAL_STATUS_DF nullptr 225 | #else 226 | #define MQTT_TOPIC_INTERNAL_STATUS_DF MQTT_TOPIC_INTERNAL_STATUS 227 | #endif 228 | #ifndef MQTT_TOPIC_INTERNAL_DEBUG_TERMINAL 229 | #define MQTT_TOPIC_INTERNAL_DEBUG_TERMINAL_DF nullptr 230 | #else 231 | #define MQTT_TOPIC_INTERNAL_DEBUG_TERMINAL_DF MQTT_TOPIC_INTERNAL_DEBUG_TERMINAL 232 | #endif 233 | #ifndef MQTT_TOPIC_UPDATE_CONTROLLER_DATETIME 234 | #define MQTT_TOPIC_UPDATE_CONTROLLER_DATETIME_DF nullptr 235 | #else 236 | #define MQTT_TOPIC_UPDATE_CONTROLLER_DATETIME_DF MQTT_TOPIC_UPDATE_CONTROLLER_DATETIME 237 | #endif 238 | #ifndef MQTT_TOPIC_UPDATE_ALL_CONTROLLER_DATA 239 | #define MQTT_TOPIC_UPDATE_ALL_CONTROLLER_DATA_DF nullptr 240 | #else 241 | #define MQTT_TOPIC_UPDATE_ALL_CONTROLLER_DATA_DF MQTT_TOPIC_UPDATE_ALL_CONTROLLER_DATA 242 | #endif 243 | #ifndef MQTT_TOPIC_BATTERY_RATED_VOLTAGE 244 | #define MQTT_TOPIC_BATTERY_RATED_VOLTAGE_DF nullptr 245 | #else 246 | #define MQTT_TOPIC_BATTERY_RATED_VOLTAGE_DF MQTT_TOPIC_BATTERY_RATED_VOLTAGE 247 | #endif 248 | #ifndef MQTT_TOPIC_BATTERY_TYPE 249 | #define MQTT_TOPIC_BATTERY_TYPE_DF nullptr 250 | #else 251 | #define MQTT_TOPIC_BATTERY_TYPE_DF MQTT_TOPIC_BATTERY_TYPE 252 | #endif 253 | #ifndef MQTT_TOPIC_BATTERY_CAPACITY 254 | #define MQTT_TOPIC_BATTERY_CAPACITY_DF nullptr 255 | #else 256 | #define MQTT_TOPIC_BATTERY_CAPACITY_DF MQTT_TOPIC_BATTERY_CAPACITY 257 | #endif 258 | #ifndef MQTT_TOPIC_BATTERY_EQUALIZATION_DURATION 259 | #define MQTT_TOPIC_BATTERY_EQUALIZATION_DURATION_DF nullptr 260 | #else 261 | #define MQTT_TOPIC_BATTERY_EQUALIZATION_DURATION_DF MQTT_TOPIC_BATTERY_EQUALIZATION_DURATION 262 | #endif 263 | #ifndef MQTT_TOPIC_BATTERY_BOOST_DURATION 264 | #define MQTT_TOPIC_BATTERY_BOOST_DURATION_DF nullptr 265 | #else 266 | #define MQTT_TOPIC_BATTERY_BOOST_DURATION_DF MQTT_TOPIC_BATTERY_BOOST_DURATION 267 | #endif 268 | #ifndef MQTT_TOPIC_BATTERY_TEMPERATURE_COMPENSATION_COEFF 269 | #define MQTT_TOPIC_BATTERY_TEMPERATURE_COMPENSATION_COEFF_DF nullptr 270 | #else 271 | #define MQTT_TOPIC_BATTERY_TEMPERATURE_COMPENSATION_COEFF_DF MQTT_TOPIC_BATTERY_TEMPERATURE_COMPENSATION_COEFF 272 | #endif 273 | #ifndef MQTT_TOPIC_BATTERY_MANAGEMENT_MODE 274 | #define MQTT_TOPIC_BATTERY_MANAGEMENT_MODE_DF nullptr 275 | #else 276 | #define MQTT_TOPIC_BATTERY_MANAGEMENT_MODE_DF MQTT_TOPIC_BATTERY_MANAGEMENT_MODE 277 | #endif 278 | #ifndef MQTT_TOPIC_STAT_ENERGY_CONSUMED_TODAY 279 | #define MQTT_TOPIC_STAT_ENERGY_CONSUMED_TODAY_DF nullptr 280 | #else 281 | #define MQTT_TOPIC_STAT_ENERGY_CONSUMED_TODAY_DF MQTT_TOPIC_STAT_ENERGY_CONSUMED_TODAY 282 | #endif 283 | #ifndef MQTT_TOPIC_STAT_ENERGY_CONSUMED_THIS_MONTH 284 | #define MQTT_TOPIC_STAT_ENERGY_CONSUMED_THIS_MONTH_DF nullptr 285 | #else 286 | #define MQTT_TOPIC_STAT_ENERGY_CONSUMED_THIS_MONTH_DF MQTT_TOPIC_STAT_ENERGY_CONSUMED_THIS_MONTH 287 | #endif 288 | #ifndef MQTT_TOPIC_STAT_ENERGY_CONSUMED_THIS_YEAR 289 | #define MQTT_TOPIC_STAT_ENERGY_CONSUMED_THIS_YEAR_DF nullptr 290 | #else 291 | #define MQTT_TOPIC_STAT_ENERGY_CONSUMED_THIS_YEAR_DF MQTT_TOPIC_STAT_ENERGY_CONSUMED_THIS_YEAR 292 | #endif 293 | #ifndef MQTT_TOPIC_STAT_ENERGY_CONSUMED_TOTAL 294 | #define MQTT_TOPIC_STAT_ENERGY_CONSUMED_TOTAL_DF nullptr 295 | #else 296 | #define MQTT_TOPIC_STAT_ENERGY_CONSUMED_TOTAL_DF MQTT_TOPIC_STAT_ENERGY_CONSUMED_TOTAL 297 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/incl/solartracer_all.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #define DUMMY_SOLAR_TRACER 0xF001 25 | 26 | #define EPEVER_SOLAR_TRACER_A 0x0001 27 | #define EPEVER_SOLAR_TRACER_B 0x0002 28 | #define EPEVER_SOLAR_TRACER_TRITON 0x0003 29 | #define EPEVER_SOLAR_TRACER_XTRA 0x0004 -------------------------------------------------------------------------------- /SolarTracerBlynk/src/incl/status_all.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #define STATUS_ERR_SOLAR_TRACER_NO_SYNC_ST 1 25 | #define STATUS_ERR_SOLAR_TRACER_NO_SYNC_RT 2 26 | #define STATUS_ERR_SOLAR_TRACER_NO_SYNC 3 27 | #define STATUS_ERR_NO_CONNECTION 4 // not used! 28 | #define STATUS_RUN_BOOTING 8 29 | #define STATUS_ERR_SOLAR_TRACER_NO_COMMUNICATION 16 30 | #define STATUS_ERR_NO_BLYNK_CONNECTION 32 31 | #define STATUS_ERR_NO_WIFI_CONNECTION 64 32 | #define STATUS_ERR_NO_MQTT_CONNECTION 128 33 | #define STATUS_ERR_LITTLEFS_BEGIN_FAILED 256 34 | #define STATUS_ERR_LITTLEFS_FORMAT_FAILED 512 35 | #define STATUS_ERR_CONFIGURATION_CANNOT_READ 1024 36 | #define STATUS_ERR_CONFIGURATION_CANNOT_PARSE 2048 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/solartracer/SolarTracer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #include "SolarTracer.h" 23 | 24 | SolarTracer::SolarTracer() { 25 | this->variableDefine = new SolarTracerVariableDefinition *[Variable::VARIABLES_COUNT](); 26 | SolarTracerVariableDefinition *value; 27 | uint8_t varSize; 28 | 29 | for (uint8_t varIndex = 0; varIndex < Variable::VARIABLES_COUNT; varIndex++) { 30 | value = nullptr; 31 | if (VariableDefiner::getInstance().isFromScc((Variable)varIndex)) { 32 | varSize = VariableDefiner::getInstance().getVariableSize((Variable)varIndex); 33 | if (varSize > 0) { 34 | value = new SolarTracerVariableDefinition{0, malloc(varSize)}; 35 | } 36 | } 37 | this->variableDefine[varIndex] = value; 38 | } 39 | } 40 | 41 | void SolarTracer::setVariableEnable(Variable variable, bool enable) { 42 | if (variable < Variable::VARIABLES_COUNT && this->variableDefine[variable] != nullptr && this->isVariableEnabled(variable) != enable) { 43 | this->variableDefine[variable]->status += enable ? 1 : -1; 44 | } 45 | } 46 | 47 | bool SolarTracer::isVariableEnabled(Variable variable) { 48 | return variable < Variable::VARIABLES_COUNT && this->variableDefine[variable] != nullptr && (this->variableDefine[variable]->status & 1) > 0; 49 | } 50 | 51 | void SolarTracer::setVariableReadReady(Variable variable, bool enable) { 52 | if (variable < Variable::VARIABLES_COUNT && this->isVariableReadReady(variable) != enable) { 53 | this->variableDefine[variable]->status += enable ? 2 : -2; 54 | } 55 | } 56 | 57 | void SolarTracer::setVariableReadReady(uint8_t count, bool ready, ...) { 58 | va_list args; 59 | va_start(args, ready); 60 | 61 | for (uint8_t i = 1; i <= count; i++) { 62 | this->setVariableReadReady((Variable)va_arg(args, int), ready); 63 | } 64 | 65 | va_end(args); 66 | } 67 | 68 | bool SolarTracer::isVariableReadReady(Variable variable) { 69 | return variable < Variable::VARIABLES_COUNT && (this->variableDefine[variable]->status & 2) > 0; 70 | } 71 | 72 | bool SolarTracer::isVariableOverWritten(Variable variable) { 73 | return variable < Variable::VARIABLES_COUNT && this->variableDefine[variable] != nullptr && (this->variableDefine[variable]->status & 4) > 0; 74 | } 75 | 76 | void SolarTracer::setVariableOverWritten(Variable variable, bool enable) { 77 | if (variable < Variable::VARIABLES_COUNT && this->isVariableOverWritten(variable) != enable) { 78 | this->variableDefine[variable]->status += enable ? 4 : -4; 79 | } 80 | } 81 | 82 | const void *SolarTracer::getValue(Variable variable) { 83 | return this->variableDefine[variable]->value; 84 | } 85 | 86 | bool SolarTracer::setVariableValue(Variable variable, const void *value, bool ignoreOverWriteLock) { 87 | if (!ignoreOverWriteLock && this->isVariableOverWritten(variable)) { 88 | return true; 89 | } 90 | bool valueOk = value != nullptr; 91 | if (valueOk) { 92 | uint8_t vSize = VariableDefiner::getInstance().getVariableSize(variable); 93 | if (vSize > 0) { 94 | memcpy(this->variableDefine[variable]->value, value, vSize); 95 | } 96 | } 97 | this->setVariableReadReady(variable, valueOk); 98 | 99 | return valueOk; 100 | } 101 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/solartracer/SolarTracer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #ifndef SOLARTRACER_H 23 | #define SOLARTRACER_H 24 | 25 | #include "../core/VariableDefiner.h" 26 | 27 | typedef void (*OnUpdateRunCompletedCallback)(); 28 | 29 | struct SolarTracerVariableDefinition { 30 | /** 31 | * byte 0 - enabled 32 | * byte 1 - ready 33 | * byte 2 - overwritten 34 | */ 35 | uint8_t status; 36 | void *value; 37 | }; 38 | 39 | class SolarTracer { 40 | public: 41 | SolarTracer(); 42 | 43 | /** 44 | * Check if the variable is supporter by the SCC 45 | */ 46 | bool isVariableEnabled(Variable variable); 47 | 48 | /** 49 | * Check if variable is ready to be read (value has been fetched from the scc) 50 | */ 51 | bool isVariableReadReady(Variable variable); 52 | 53 | /** 54 | * Check if variable has been overwritten 55 | */ 56 | bool isVariableOverWritten(Variable variable); 57 | 58 | /** 59 | * Set variable as overwritten (not managed by the scc) 60 | */ 61 | void setVariableOverWritten(Variable variable, bool enable); 62 | 63 | /** 64 | * Get the value of the variable, null if variable is not ready 65 | */ 66 | virtual const void *getValue(Variable variable); 67 | 68 | /** 69 | * Set the value of the variable 70 | */ 71 | bool setVariableValue(Variable variable, const void *value, bool ignoreOverWriteLock = false); 72 | 73 | void setOnUpdateRunCompleted(OnUpdateRunCompletedCallback fn) { 74 | this->onUpdateRunCompleted = fn; 75 | } 76 | 77 | /** 78 | * Return last status code, 0 means the controller is responding to requests correctly. 79 | */ 80 | inline const uint16_t getLastControllerCommunicationStatus(); 81 | 82 | virtual bool fetchValue(Variable variable) = 0; 83 | virtual bool syncRealtimeClock(struct tm *ti) = 0; 84 | virtual void fetchAllValues() = 0; 85 | virtual bool updateRun() = 0; 86 | virtual bool writeValue(Variable variable, const void *value) = 0; 87 | virtual bool testConnection() = 0; 88 | 89 | protected: 90 | inline bool setFloatVariable(Variable variable, float value); 91 | 92 | void updateRunCompleted() { 93 | if (this->onUpdateRunCompleted) { 94 | this->onUpdateRunCompleted(); 95 | } 96 | } 97 | 98 | void setVariableEnable(Variable variable, bool enable = true); 99 | 100 | void setVariableReadReady(Variable variable, bool enable); 101 | 102 | void setVariableReadReady(uint8_t count, bool ready, ...); 103 | 104 | uint16_t lastControllerCommunicationStatus; 105 | 106 | private: 107 | OnUpdateRunCompletedCallback onUpdateRunCompleted = nullptr; 108 | SolarTracerVariableDefinition **variableDefine; 109 | }; 110 | 111 | inline const uint16_t SolarTracer::getLastControllerCommunicationStatus() { 112 | return this->lastControllerCommunicationStatus; 113 | } 114 | 115 | inline bool SolarTracer::setFloatVariable(Variable variable, float value) { 116 | return this->setVariableValue(variable, &value); 117 | } 118 | 119 | #endif 120 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/solartracer/dummy/DummySolarTracer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #ifndef DUMMYSOLARTRACER_H 23 | #define DUMMYSOLARTRACER_H 24 | 25 | #include "../../core/VariableDefiner.h" 26 | #include "../SolarTracer.h" 27 | 28 | class DummySolarTracer : public SolarTracer { 29 | public: 30 | DummySolarTracer() : SolarTracer() { 31 | this->dummyTextValue = new char[20]; 32 | 33 | bool enabled; 34 | for (uint8_t index = 0; index < Variable::VARIABLES_COUNT; index++) { 35 | if (VariableDefiner::getInstance().isFromScc((Variable)index)) { 36 | this->setVariableEnable((Variable)index, true); 37 | this->setVariableReadReady((Variable)index, true); 38 | } 39 | } 40 | }; 41 | 42 | virtual bool fetchValue(Variable variable) { 43 | return true; 44 | }; 45 | virtual bool syncRealtimeClock(struct tm *ti) { 46 | return true; 47 | } 48 | virtual void fetchAllValues(){}; 49 | virtual bool updateRun() { 50 | return true; 51 | }; 52 | virtual bool writeValue(Variable variable, const void *value) { 53 | return true; 54 | }; 55 | virtual bool testConnection() { 56 | return true; 57 | }; 58 | 59 | virtual const void *getValue(Variable variable) { 60 | switch (VariableDefiner::getInstance().getDatatype(variable)) { 61 | case VariableDatatype::DT_BOOL: 62 | this->dummyBoolValue = random(2) > 0; 63 | return &this->dummyBoolValue; 64 | case VariableDatatype::DT_FLOAT: 65 | this->dummyFloatValue = random(10000) / 100.00; 66 | return &this->dummyFloatValue; 67 | case VariableDatatype::DT_STRING: 68 | strcpy(this->dummyTextValue, "Text"); 69 | return this->dummyTextValue; 70 | case VariableDatatype::DT_UINT16: 71 | this->dummyUInt16 = random(100) > 0; 72 | return &this->dummyUInt16; 73 | } 74 | return nullptr; 75 | } 76 | 77 | private: 78 | bool dummyBoolValue; 79 | float dummyFloatValue; 80 | char *dummyTextValue; 81 | uint16_t dummyUInt16; 82 | }; 83 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/solartracer/epever/EPEVERSolarTracer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #ifndef EPEVERSolarTracer_h 23 | #define EPEVERSolarTracer_h 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "../SolarTracer.h" 30 | 31 | class EPEVERSolarTracer : public SolarTracer, public ModbusMasterCallable { 32 | public: 33 | EPEVERSolarTracer(Stream &serialCom, uint16_t serialTimeoutMs, uint8_t slave, uint8_t max485_de, uint8_t max485_re_neg, uint16_t preTransmitWait); 34 | EPEVERSolarTracer(Stream &serialCom, uint16_t serialTimeoutMs, uint8_t slave, uint16_t preTransmitWait); 35 | 36 | virtual bool syncRealtimeClock(struct tm *ti); 37 | 38 | virtual void fetchAllValues(); 39 | 40 | virtual bool updateRun(); 41 | 42 | virtual bool fetchValue(Variable variable); 43 | 44 | virtual bool writeValue(Variable variable, const void *value); 45 | 46 | bool readControllerSingleCoil(uint16_t address); 47 | 48 | void AddressRegistry_3100(); 49 | 50 | void AddressRegistry_3110(); 51 | 52 | void AddressRegistry_311A(); 53 | 54 | void AddressRegistry_331B(); 55 | 56 | void AddressRegistry_9003(); 57 | 58 | void AddressRegistry_9067(); 59 | 60 | void AddressRegistry_906B(); 61 | 62 | void fetchAddressStatusVariables(); 63 | 64 | void updateStats(); 65 | 66 | /* 67 | Implementation of ModbusMasterCallable 68 | */ 69 | virtual void onModbusPreTransmission(); 70 | 71 | virtual void onModbusIdle(); 72 | 73 | virtual void onModbusPostTransmission(); 74 | 75 | virtual bool testConnection(); 76 | 77 | protected: 78 | uint8_t max485_re_neg, max485_de; 79 | uint16_t preTransmitWaitMs; 80 | 81 | bool rs485readSuccess; 82 | 83 | uint16_t globalUpdateCounter = 0; 84 | uint8_t currentRealtimeUpdateCounter = 0; 85 | 86 | ModbusMaster node; 87 | 88 | // MODBUS FUNCTION 89 | 90 | bool writeControllerSingleCoil(uint16_t address, bool value); 91 | bool writeControllerHoldingRegister(uint16_t address, uint16_t value); 92 | bool replaceControllerHoldingRegister(uint16_t address, uint16_t value, uint16_t fromAddress, uint8_t count); 93 | 94 | static constexpr const float ONE_HUNDRED_FLOAT = 100; 95 | 96 | private: 97 | static const uint8_t voltageLevels[]; 98 | 99 | void onPreNodeRequest() { 100 | if (this->preTransmitWaitMs > 0) { 101 | delay(this->preTransmitWaitMs); 102 | } 103 | } 104 | 105 | static uint16_t getBatteryVoltageLevelFromVoltage(uint16_t voltage) { 106 | uint8_t index = 0; 107 | while (true) { 108 | if (voltageLevels[index] == 0) { 109 | return 0; 110 | } 111 | if (voltageLevels[index] == voltage) { 112 | return index + 1; 113 | } 114 | index++; 115 | } 116 | } 117 | 118 | static uint16_t getVoltageFromBatteryVoltageLevel(uint16_t index) { 119 | return voltageLevels[index]; 120 | } 121 | }; 122 | 123 | #endif 124 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/solartracer/epever/EPEVER_modbus_address.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #ifndef EPEVER_modbus_address_h 23 | #define EPEVER_modbus_address_h 24 | 25 | #define MODBUS_ADDRESS_PV_VOLTAGE 0x3100 26 | #define MODBUS_ADDRESS_PV_POWER 0x3102 27 | #define MODBUS_ADDRESS_PV_CURRENT 0x3101 28 | #define MODBUS_ADDRESS_LOAD_CURRENT 0x310D 29 | #define MODBUS_ADDRESS_LOAD_POWER 0x310E 30 | #define MODBUS_ADDRESS_BATT_TEMP 0x3110 31 | #define MODBUS_ADDRESS_BATT_VOLTAGE 0x3104 32 | #define MODBUS_ADDRESS_BATT_SOC 0x311A 33 | #define MODBUS_ADDRESS_BATTERY_CHARGE_CURRENT 0x3105 34 | #define MODBUS_ADDRESS_BATTERY_CHARGE_POWER 0x3106 35 | #define MODBUS_ADDRESS_BATTERY_OVERALL_CURRENT 0x331B 36 | #define MODBUS_ADDRESS_LOAD_FORCE_ONOFF 0x0006 37 | #define MODBUS_ADDRESS_LOAD_MANUAL_ONOFF 0x0002 38 | #define MODBUS_ADDRESS_BATTERY_CHARGE_ONOFF 0x0000 39 | #define MODBUS_ADDRESS_BATTERY_STATUS 0x3200 40 | #define MODBUS_ADDRESS_CHARGING_EQUIPMENT_STATUS 0x3200 41 | #define MODBUS_ADDRESS_DISCHARGING_EQUIPMENT_STATUS 0x3200 42 | #define MODBUS_ADDRESS_STAT_MAX_PV_VOLTAGE_TODAY 0x3300 43 | #define MODBUS_ADDRESS_STAT_CONSUMED_ENERGY_TODAY 0x3304 44 | #define MODBUS_ADDRESS_STAT_CONSUMED_ENERGY_MONTH 0x3306 45 | #define MODBUS_ADDRESS_STAT_CONSUMED_ENERGY_YEAR 0x3308 46 | #define MODBUS_ADDRESS_STAT_GENERATED_ENERGY_TODAY 0x330C 47 | #define MODBUS_ADDRESS_STAT_GENERATED_ENERGY_MONTH 0x330E 48 | #define MODBUS_ADDRESS_STAT_GENERATED_ENERGY_YEAR 0x3310 49 | #define MODBUS_ADDRESS_CONTROLLER_TEMP 0x3111 50 | #define MODBUS_ADDRESS_REMOTE_BATTERY_TEMP 0x311B 51 | #define MODBUS_ADDRESS_REALTIME_CLOCK 0x9013 52 | #define MODBUS_ADDRESS_BATTERY_TYPE 0x9000 53 | #define MODBUS_ADDRESS_BATTERY_CAPACITY 0x9001 54 | #define MODBUS_ADDRESS_BATTERY_TEMP_COEFF 0x9002 55 | #define MODBUS_ADDRESS_HIGH_VOLTAGE_DISCONNECT 0x9003 56 | #define MODBUS_ADDRESS_CHARGING_LIMIT_VOLTAGE 0x9004 57 | #define MODBUS_ADDRESS_OVER_VOLTAGE_RECONNECT 0x9005 58 | #define MODBUS_ADDRESS_EQUALIZATION_VOLTAGE 0x9006 59 | #define MODBUS_ADDRESS_BOOST_VOLTAGE 0x9007 60 | #define MODBUS_ADDRESS_FLOAT_VOLTAGE 0x9008 61 | #define MODBUS_ADDRESS_BOOST_RECONNECT_VOLTAGE 0x9009 62 | #define MODBUS_ADDRESS_LOW_VOLTAGE_RECONNECT 0x900A 63 | #define MODBUS_ADDRESS_UNDER_VOLTAGE_RECOVER 0x900B 64 | #define MODBUS_ADDRESS_UNDER_VOLTAGE_WARNING 0x900C 65 | #define MODBUS_ADDRESS_LOW_VOLTAGE_DISCONNECT 0x900D 66 | #define MODBUS_ADDRESS_DISCHARGING_LIMIT_VOLTAGE 0x900E 67 | #define MODBUS_ADDRESS_BATTERY_RATED_LEVEL 0x9067 68 | #define MODBUS_ADDRESS_EQUALIZE_DURATION 0x906B 69 | #define MODBUS_ADDRESS_BOOST_DURATION 0x906C 70 | #define MODBUS_ADDRESS_CHARGING_MODE 0x9070 71 | 72 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/solartracer/epever/epever_config.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #include "../../incl/include_all_core.h" 25 | 26 | #ifndef BOARD_ST_SERIAL_STREAM_BAUDRATE 27 | #define BOARD_ST_SERIAL_STREAM_BAUDRATE 115200 28 | #endif 29 | 30 | #ifndef MODBUS_SLAVE_ID 31 | #define MODBUS_SLAVE_ID 1 32 | #endif 33 | 34 | #ifndef CONTROLLER_UPDATE_MS_PERIOD 35 | #define CONTROLLER_UPDATE_MS_PERIOD 2000L 36 | #endif 37 | 38 | #ifndef SERIAL_COMMUNICATION_TIMEOUT 39 | // will use the default value from library 40 | #define SERIAL_COMMUNICATION_TIMEOUT 0 41 | #endif 42 | -------------------------------------------------------------------------------- /SolarTracerBlynk/src/solartracer/incl/solar_config.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #include "../epever/epever_config.h" 23 | 24 | #if (SOLAR_TRACER_MODEL == EPEVER_SOLAR_TRACER_A | SOLAR_TRACER_MODEL == EPEVER_SOLAR_TRACER_B | SOLAR_TRACER_MODEL == EPEVER_SOLAR_TRACER_TRITON | SOLAR_TRACER_MODEL == EPEVER_SOLAR_TRACER_XTRA) 25 | #include "../epever/EPEVERSolarTracer.h" 26 | #ifdef USE_SERIAL_MAX485 27 | #define SOLAR_TRACER_INSTANCE EPEVERSolarTracer(BOARD_ST_SERIAL_STREAM, SERIAL_COMMUNICATION_TIMEOUT, MODBUS_SLAVE_ID, MAX485_DE, MAX485_RE_NEG, BOARD_ST_SERIAL_PRETRANSMIT_WAIT) 28 | #else 29 | #define SOLAR_TRACER_INSTANCE EPEVERSolarTracer(BOARD_ST_SERIAL_STREAM, SERIAL_COMMUNICATION_TIMEOUT, MODBUS_SLAVE_ID, BOARD_ST_SERIAL_PRETRANSMIT_WAIT) 30 | #endif 31 | #elif (SOLAR_TRACER_MODEL == DUMMY_SOLAR_TRACER) 32 | #include "../dummy/DummySolarTracer.h" 33 | #define SOLAR_TRACER_INSTANCE DummySolarTracer() 34 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/solartracer/overwrite/LoadCurrentOverWrite.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../../incl/include_all_core.h" 3 | 4 | #ifdef USE_EXTERNAL_HEAVY_LOAD_CURRENT_METER 5 | 6 | #include "LoadCurrentOverwrite.h" 7 | 8 | float LoadCurrentOverwrite::totalLoadEnergy = 0; 9 | LinearSensHallCurrent *LoadCurrentOverwrite::sensor = nullptr; 10 | #ifdef USE_EXTERNAL_HEAVY_LOAD_CURRENT_METER_ADS1015_ADC 11 | ADS1015 *LoadCurrentOverwrite::ads1015 = nullptr; 12 | #endif 13 | unsigned long LoadCurrentOverwrite::lastRunMillis = 0; 14 | 15 | #endif -------------------------------------------------------------------------------- /SolarTracerBlynk/src/solartracer/overwrite/LoadCurrentOverwrite.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solar Tracer Blynk V3 [https://github.com/Bettapro/Solar-Tracer-Blynk-V3] 3 | * Copyright (c) 2021 Alberto Bettin 4 | * 5 | * Based on the work of @jaminNZx and @tekk. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | * 20 | */ 21 | 22 | #pragma once 23 | 24 | #ifndef LOAD_CURRENT_OVERWRITE_H 25 | #define LOAD_CURRENT_OVERWRITE_H 26 | 27 | #include "../../incl/include_all_core.h" 28 | 29 | #ifdef USE_EXTERNAL_HEAVY_LOAD_CURRENT_METER 30 | 31 | #include "../../core/Environment.h" 32 | #include "../../incl/include_all_lib.h" 33 | #include "../SolarTracer.h" 34 | 35 | class LoadCurrentOverwrite { 36 | public: 37 | static void setup(SolarTracer *tracer) { 38 | totalLoadEnergy = 0; 39 | lastRunMillis = 0; 40 | 41 | #ifdef USE_EXTERNAL_HEAVY_LOAD_CURRENT_METER_ADS1015_ADC 42 | ads1015 = new ADS1015(0x48); 43 | ads1015->begin(); 44 | 45 | ads1015->setGain(0); 46 | 47 | sensor = new LinearSensHallCurrent(LinearSensHallCurrentType::CUSTOM, 0, 6.144, 11); 48 | sensor->setRawReadFn([]() { 49 | int adp_value = ads1015->readADC(ADS1015_LOAD_CURRENT_CHANNEL); 50 | return adp_value; }); 51 | #endif 52 | #ifdef USE_EXTERNAL_HEAVY_LOAD_CURRENT_ADC 53 | sensor = new LinearSensHallCurrent(LinearSensHallCurrentType::CUSTOM, ADC_LOAD_CURRENT_PIN, 3.3, 12); 54 | #endif 55 | 56 | sensor->setZeroVout(Environment::getData()->heavyLoadCurrentZeroV); 57 | sensor->setSampleNumber(EXTERNAL_HEAVY_LOAD_CURRENT_METER_SAMPLES_NUMBER); 58 | sensor->setSampleDelay(EXTERNAL_HEAVY_LOAD_CURRENT_METER_SAMPLE_INTERVAL); 59 | sensor->setVASensitivity(EXTERNAL_HEAVY_LOAD_CURRENT_METER_VOLTAGE_AMP_VOLT); 60 | 61 | tracer->setVariableOverWritten(Variable::LOAD_CURRENT, true); 62 | tracer->setVariableOverWritten(Variable::LOAD_POWER, tracer->isVariableEnabled(Variable::BATTERY_VOLTAGE)); 63 | tracer->setVariableOverWritten(Variable::CONSUMED_ENERGY_TODAY, tracer->isVariableEnabled(Variable::BATTERY_VOLTAGE)); 64 | tracer->setVariableOverWritten(Variable::CONSUMED_ENERGY_MONTH, tracer->isVariableEnabled(Variable::BATTERY_VOLTAGE)); 65 | tracer->setVariableOverWritten(Variable::CONSUMED_ENERGY_YEAR, tracer->isVariableEnabled(Variable::BATTERY_VOLTAGE)); 66 | tracer->setVariableOverWritten(Variable::CONSUMED_ENERGY_TOTAL, tracer->isVariableEnabled(Variable::BATTERY_VOLTAGE)); 67 | tracer->setVariableOverWritten(Variable::BATTERY_OVERALL_CURRENT, tracer->isVariableEnabled(Variable::BATTERY_CHARGE_CURRENT)); 68 | } 69 | 70 | static void overWrite(SolarTracer *tracer) { 71 | float current = sensor->readCurrent(); 72 | if (current > 1000) { 73 | // not happening 74 | return; 75 | } 76 | if (current < 0) { 77 | // loads do not produce any current, must be a false reading 78 | current = 0; 79 | } 80 | tracer->setVariableValue(Variable::LOAD_CURRENT, ¤t, true); 81 | 82 | if (tracer->isVariableReadReady(Variable::BATTERY_CHARGE_CURRENT)) { 83 | const void *chargingCurrent = tracer->getValue(Variable::BATTERY_CHARGE_CURRENT); 84 | float overallCurrent = *(float *)chargingCurrent - current; 85 | tracer->setVariableValue(Variable::BATTERY_OVERALL_CURRENT, &overallCurrent, true); 86 | } 87 | 88 | const void *loadVoltage = tracer->getValue(Variable::BATTERY_VOLTAGE); 89 | 90 | if (!tracer->isVariableReadReady(Variable::BATTERY_VOLTAGE) || loadVoltage == nullptr) { 91 | return; 92 | } 93 | 94 | unsigned long currentRunMillis = millis(); 95 | 96 | float loadPower = current * *((float *)loadVoltage); 97 | float loadEnergy = lastRunMillis > 0 ? (currentRunMillis - lastRunMillis) / 3600000000.0 * loadPower : 0; 98 | lastRunMillis = currentRunMillis; 99 | 100 | tracer->setVariableValue(Variable::LOAD_POWER, &loadPower, true); 101 | 102 | totalLoadEnergy += loadEnergy; 103 | tracer->setVariableValue(Variable::CONSUMED_ENERGY_TODAY, &totalLoadEnergy, true); 104 | tracer->setVariableValue(Variable::CONSUMED_ENERGY_MONTH, &totalLoadEnergy, true); 105 | tracer->setVariableValue(Variable::CONSUMED_ENERGY_YEAR, &totalLoadEnergy, true); 106 | tracer->setVariableValue(Variable::CONSUMED_ENERGY_TOTAL, &totalLoadEnergy, true); 107 | } 108 | 109 | private: 110 | static float totalLoadEnergy; 111 | static LinearSensHallCurrent *sensor; 112 | #ifdef USE_EXTERNAL_HEAVY_LOAD_CURRENT_METER_ADS1015_ADC 113 | static ADS1015 *ads1015; 114 | #endif 115 | static unsigned long lastRunMillis; 116 | }; 117 | 118 | #endif 119 | #endif -------------------------------------------------------------------------------- /docs/1733_modbus_protocol.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/docs/1733_modbus_protocol.pdf -------------------------------------------------------------------------------- /docs/Esp32_max485_epever_rj45.md: -------------------------------------------------------------------------------- 1 | # Connect ESP32 to EPEVER A/B Series ( + MAX485) 2 | 3 | Here the material involved: 4 | * ESP 32 MODULE, below the modules tested: 5 | * [ESP32 D1 MINI](https://www.aliexpress.com/premium/esp32-d1-mini.html?d=y&origin=y&catId=0&initiative_id=SB_20210919083440&SearchText=esp32%20d1%20mini) 6 | * [ESP32 WROOM DEV MODULE](https://it.aliexpress.com/wholesale?catId=0&initiative_id=SB_20210919092741&isPremium=y&SearchText=esp+wroom-32+38+pin+devkit) 7 | * or any esp32 module you like 8 | * [EPSolar/EPEver Tracer A/B-Series](https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20170114172728&SearchText=tracer+mppt+rs485) 9 | * [MAX 485 UART Module](https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20210919083609&isPremium=y&SearchText=max485+module) 10 | * An old ethernet cable with RJ45 connector you are happy to cut open 11 | 12 | 13 | ## ESP32 <-> MAX485 module 14 | 15 | ![This one worked for me](../images/max485_module.jpg) 16 | 17 | It's powered from `+5V` from ESP32 module, and wired as following: 18 | 19 | ### ESP32 D1 MINI 20 | - `DI` -> `IO17` / `GPIO17` / `TX2` 21 | - `RO` -> `IO16` / `GPIO16` / `RX2` 22 | - `DE` and `RE` are interconnected with a jumper and then connected to pin `TCK` / `GPIO13` 23 | - `VCC` to `+3.3V` / `3V3` on ESP32 24 | 25 | 26 | ![ESP32 D1 MINI](../images/esp32_d1_mini_pins.png) 27 | 28 | ### ESP32 WRROOM 38 PIN 29 | - `DI` -> `28` / `GPIO17` / `TX2` 30 | - `RO` -> `27` / `GPIO16` / `RX2` 31 | - `DE` and `RE` are interconnected with a jumper and then connected to pin `15` / `GPIO13` 32 | - `VCC` to `+3.3V` / `3.3v` on ESP32 33 | 34 | ![ESP32 WRROOM 38 PIN](../images/esp32_wroom_38_pin.jpg) 35 | 36 | ## MAX485 module <-> EPEVER CONTROLLER (RJ45) 37 | 38 | Cut open your ethernet cable and split out pin 4, 6, 8 (B, A, GND). Refer to [Tracer Modbus PDF](../docs/1733_modbus_protocol.pdf) for additional info. 39 | 40 | Connect wires as follows (make sure your cable matches the color schema below - otherwise refer to pin numbers only): 41 | - Ethernet green / pin `6` -> `A` 42 | - Ethernet blue / pin `4` -> `B` 43 | - Ethernet brown / pin `8` -> `GND` on module **and** ESP8266 `GND` pin 44 | - -> to prevent ground loops - **important!** 45 | - **DON' T** use pin `1` or `2` to feed the ESP8266 (they supply 7,5/5V - 50mA maximum) 46 | 47 | ![EPEVER RJ485 SPEC](../images/epever_rj45_specs.png) 48 | ![ETH_T586B](../images/eth_t568b.png) 49 | 50 | ## BASE SW CONFIGURATION 51 | 52 | Edits required on *src/config.h*: 53 | - `#define BOARD_ST_SERIAL_STREAM Serial2` [default] 54 | - Uncomment `#define USE_SERIAL_MAX485` 55 | - `#define MAX485_DE 13` 56 | - `#define MAX485_RE_NEG 13` 57 | 58 | Edit on *platformio.ini* (Platformio only): 59 | - **ESP32 MINI D1 - only** 60 | - `platformio.default_envs = wemos_d1_mini32` (usb/serial fw flash) or `platformio.default_envs = wemos_d1_mini32_ota` (ota fw flash) 61 | - **ESP32 DEV MODULE - only** 62 | - `platformio.default_envs = esp32dev` (usb/serial fw flash) or `platformio.default_envs = esp32dev_ota` (ota fw flash) 63 | 64 | You may need to make more changes according to your needs (ntp syn/led status/ data to monitor ...). 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/Esp8266_max485_epever_rj45.md: -------------------------------------------------------------------------------- 1 | # Connect ESP8266 to EPEVER A/B Series ( + MAX485) 2 | 3 | Here the material involved: 4 | * [ESP8266 Dev Board](https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20170114172938&SearchText=esp8266+mini) 5 | * [EPSolar/EPEver Tracer A/B-Series](https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20170114172728&SearchText=tracer+mppt+rs485) 6 | * [RS485 UART Module](https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20170114172807&SearchText=uart+rs485) (~~not the MAX485 chip!~~ - `@tekk:` I'm using [MAX485 cheapo module](../images/max485_module.jpg) and it works fine!) 7 | * An old ethernet cable with RJ45 connector you are happy to cut open 8 | 9 | 10 | ## ESP8266 <-> MAX485 module 11 | 12 | Required connections: 13 | - `DI` -> `D10` / `GPIO1` / `TX` 14 | - `RO` -> `D9` / `GPIO3` / `RX` 15 | - `DE` and `RE` are interconnected with a jumper and then connected to pin `D1` / `GPIO5` 16 | - `VCC` to `3.3V` on ESP8266 17 | 18 | ![Alt text](../images/esp8266_hw_serial.png) 19 | 20 | ## ESP8266 <-> MAX485 module + SOFTWARE SERIAL (since v3.0.7) 21 | 22 | Required connections: 23 | - `DI` -> `D2` / `GPIO4` 24 | - `RO` -> `D4` / `GPIO2` 25 | - `DE` and `RE` are interconnected with a jumper and then connected to pin `D1` / `GPIO5` 26 | - `VCC` to `3.3V` on ESP8266 27 | 28 | ![Alt text](../images/esp8266_sw_serial.png) 29 | 30 | ## MAX485 module <-> EPEVER CONTROLLER (RJ45) 31 | 32 | Cut open your ethernet cable and split out pin 4, 6, 8 (B, A, GND). Refer to [Tracer Modbus PDF](../docs/1733_modbus_protocol.pdf) for additional info. 33 | 34 | Connect wires as follows (make sure your cable matches the color schema below - otherwise refer to pin numbers only): 35 | - Ethernet green / pin `6` -> `A` 36 | - Ethernet blue / pin `4` -> `B` 37 | - Ethernet brown / pin `8` -> `GND` on module **and** ESP8266 `GND` pin 38 | - -> to prevent ground loops - **important!** 39 | - **DON' T** use pin `1` or `2` to feed the ESP8266 (they supply 7,5/5V - 50mA maximum) 40 | 41 | ![EPEVER RJ485 SPEC](../images/epever_rj45_specs.png) 42 | ![ETH_T586B](../images/eth_t568b.png) 43 | 44 | -------------------------------------------------------------------------------- /docs/Sw_getting_started.md: -------------------------------------------------------------------------------- 1 | # SW getting started 2 | 3 | ## 1a. Flash a pre-built firmware 4 | Download the most recent version of the firmware https://github.com/Bettapro/Solar-Tracer-Blynk-V3/releases . 5 | 6 | Download the correct bif file depending on the board you're gonna use: 7 | - SolarTracerBlynk_3.x.x_esp32dev_FULL.bin - full bin file to use on a ESP32 (it includes all the bin needed eg: bootloader, firmware ...), use it on the very first setup. 8 | - SolarTracerBlynk_3.x.x_esp8266.bin - bin file to use on a ESP8266. 9 | 10 | Download [esp_flash_download_tool](https://www.espressif.com/en/support/download/other-tools). 11 | 12 | Start esp_flash_download_tool and select the correct board 13 | 14 | ![esp_tool_board_select](../images/esp_tool_board_select.png) 15 | 16 | Load the bin downloaded, set the address to 0x0000, and press START. 17 | 18 | ![esp_tool_board_select](../images/esp_tool_bin_flash_new.png) 19 | 20 | **You board is ready!** 21 | 22 | ## 1b. Build manually 23 | Download the most recent version of this project https://github.com/Bettapro/Solar-Tracer-Blynk-V3/releases 24 | 25 | Open you favorite IDE: 26 | - Arduino IDE: open *SolarTracerBlynk* folder, then open *SolarTracerBlynk.ino* . 27 | - Platformio: import the project using *platformio.ini* . 28 | 29 | ### Libraries to include in Arduino IDE 30 | 31 | 32 | 33 | * [ArduinoOTA](https://github.com/esp8266/Arduino/tree/master/libraries/ArduinoOTA) 34 | * [ModbusMaster](https://github.com/Bettapro/ModbusMaster) 35 | * [WiFiManager](https://github.com/tzapu/WiFiManager) 36 | * [ArduinoJson](https://github.com/bblanchon/ArduinoJson) 37 | * [PubSubClient](https://github.com/knolleary/pubsubclient) - MQTT ONLY 38 | * [Blynk Library](https://github.com/blynkkk/blynk-library) - BLYNK ONLY 39 | * [SimpleTimer](https://github.com/Bettapro/SimpleTimer) - MQTT ONLY 40 | 41 | 42 | ### Edit `config.h` library 43 | Open `SolarTracerBlynk\config.h` 44 | 45 | * Enter your WiFi credentials in `WIFI_SSID` and `WIFI_PASS`. 46 | * Send yourself the generated auth code from the mobile app 47 | * Paste your auth code into `BLYNK_AUTH` 48 | 49 | You can customize further more modifying config.h (eg. status LED, ntp time sync, blynk serve ...), each option is documented on the config.h file. 50 | Please refer to the notes written on it. 51 | 52 | ### Upload firmware 53 | 54 | Upload the sketch to your ESP8266 / ESP32, if you are using platformio you should edit `default_envs` accordingly (eg: *esp8266* to use a esp8266, *esp8266_ota* to update ESP8266 via OTA, *esp32dev* to use and ESP32, .... ) 55 | 56 | **You board is ready!** 57 | 58 | ## 2. Mobile App 59 | 60 | Get the Mobile App ([iOS](https://itunes.apple.com/us/app/blynk-iot-for-arduino-rpi/id808760481?mt=8) & [Android](https://play.google.com/store/apps/details?id=cc.blynk&hl=en)) 61 | 62 | Open the Blynk mobile app and create a new project by scanning the following QR code. 63 | 64 | Click PLAY on you mobile app, you should start receiving updates from your solar tracer!. 65 | 66 | 67 | ### Legacy app (v3) - SUGGESTED 68 | Current version of the app, complete overview of the solar charge controller. ENERGY REQUIRED: 14300 69 | 70 | ![Project QR Code](../images/blynk-app-qr-code_v3_blynkcloud.png) 71 | 72 | ### Legacy app (v2) 73 | Original version of the mobile app, shows a small set of data. ENERGY REQUIRED: 4400 74 | 75 | ![Project QR Code](../images/blynk-app-qr-code.png) 76 | 77 | 78 | ## 3. Wifi Configuration (SETUP MODE) 79 | 80 | You can configure your board via a web interface. 81 | 82 | Device will try to connect to your wifi network, if the connection fails, it will turn to AP mode and create a new wifi network. 83 | You can trigger the setup mode by putting in HIGH status (3.3v) pin 19 for few seconds(default value, check your config.h) just after you pressed the reset button. 84 | 85 | **NOTE:** ESP32 could switch to this mode using the hall sensor, just press the reset button and keep a magnet close to the board (please make sure this feature is enabled in your firmware) 86 | 87 | Default values: 88 | - WIFI SSID: SolarTracerAP 89 | - WIFI PASSWORD: admin1234 90 | 91 | Connect to this Wifi network, then open a web browser and go to http://192.168.4.1 . 92 | 93 | ![wifimanager_home](../images/wifi_manager_home.png) 94 | 95 | Click on Configure and fill the form with your data. 96 | 97 | ![wifimanager_config](../images/wifi_manager_config.png) 98 | 99 | 100 | ## 4.Update 101 | You can update your board just by compiling and flashing the new firmware as explained in point **1b** . 102 | 103 | Otherwise, you should trigger the setup mode manually and you the UPDATE button. 104 | 105 | Download the most recent version of the firmware https://github.com/Bettapro/Solar-Tracer-Blynk-V3/releases . 106 | - SolarTracerBlynk_3.x.x_esp32dev.bin - ESP32 only 107 | - SolarTracerBlynk_3.x.x_esp8266.bin - ESP8266 only 108 | 109 | Load the bin file into the form shown and press update. 110 | 111 | -------------------------------------------------------------------------------- /docs/esp32.md: -------------------------------------------------------------------------------- 1 | # ESP32 2 | 3 | ## HOW TO FLASH 4 | 5 | You need: 6 | - one bin file, the firmware you want to install on your ESP32 7 | - [esp flasher tool](https://www.espressif.com/en/support/download/other-tools) 8 | 9 | **NOTE:** The board has to be prepared the first time you use it, by flashing a particular bin file as described [below](#first-time-setup). This has to be done only once, then, you can install the firmware via [COM](#com-firmware-upgrade) or [WEB](#wifi-firmware-upgrade). 10 | 11 | --- 12 | ### First time setup 13 | 14 | The very first time you process with the firmware flash, you must prepare your board. 15 | 16 | You need one additional bin file, you can download it [here](https://github.com/Bettapro/Solar-Tracer-Blynk-V3/releases/download/v3.0.4/SolarTracerBlynk_3.0.4_esp32dev_FULL.bin) 17 | This bin file contains a complete image of the flash memory. 18 | 19 | Start esp_flash_download_tool and select the correct board (ESP32): 20 | ![esp_tool_board_select](../images/esp_tool_board_select.png) 21 | 22 | Load the bin "SolarTracerBlynk_3.0.4_esp32dev_FULL.bin", set the address to 0x0000. 23 | ![esp_tool_board_select](../images/esp_tool_bin_flash_new.png) 24 | 25 | Select the correct COM port and then press START, it should take some time the complete the process. 26 | Reboot board, you should see a new access point named "Solar tracer", if so, you are ready to upgrade to the REAL firmware. 27 | 28 | --- 29 | ### COM firmware upgrade 30 | You will upgrade your firmware using the COM serial port. 31 | 32 | Start esp_flash_download_tool and select the correct board (ESP32): 33 | ![esp_tool_board_select](../images/esp_tool_board_select.png) 34 | 35 | Load the bin set the address to 0x10000. 36 | ![esp_tool_board_address](../images/esp_tool_bin_flash_10000.png) 37 | 38 | Select the correct COM port and then press START, it should take some time the complete the process. 39 | Reboot board, upgrade completed! 40 | 41 | --- 42 | ### WIFI firmware upgrade 43 | You will upgrade your firmware using the web interface. 44 | 45 | Start your ESP32 in configuration mode, the board will create an access point (normally named "Solar tracer"). 46 | 47 | Connect to the AP, open a new tab on your web browser and go to http://192.168.4.1 . 48 | 49 | Click INFO. 50 | ![wifimanager_home](../images/wifi_manager.png) 51 | 52 | Click UPDATE. 53 | ![wifimanager_info](../images/wifi_manager_update.png) 54 | 55 | Load the bin file and start the update. 56 | ![wifimanager_info](../images/wifi_manager_update_upload.png) 57 | 58 | Reboot board, upgrade completed! -------------------------------------------------------------------------------- /docs/esp8266.md: -------------------------------------------------------------------------------- 1 | # ESP8266 2 | 3 | ## HOW TO FLASH 4 | 5 | You need: 6 | - one bin file, the firmware you want to install on your ESP8266 7 | - [esp flasher tool](https://www.espressif.com/en/support/download/other-tools) 8 | 9 | --- 10 | ### COM firmware upgrade 11 | You will upgrade your firmware using the COM serial port. 12 | 13 | Start esp_flash_download_tool and select the correct board (ESP8266): 14 | ![esp_tool_board_select](../images/esp_tool_board_select.png) 15 | 16 | Load the bin set the address to 0x0. 17 | ![esp_tool_board_address](../images/esp8266_bin_flash.png) 18 | 19 | Select the correct COM port and then press START, it should take some time the complete the process. 20 | Reboot board, upgrade completed! 21 | 22 | --- 23 | ### WIFI firmware upgrade 24 | You will upgrade your firmware using the web interface. 25 | 26 | Start your ESP8266 in configuration mode, the board will create an access point (normally named "Solar tracer"). 27 | 28 | Connect to the AP, open a new tab on your web browser and go to http://192.168.4.1 . 29 | 30 | Click INFO. 31 | ![wifimanager_home](../images/wifi_manager.png) 32 | 33 | Click UPDATE. 34 | ![wifimanager_info](../images/wifi_manager_update.png) 35 | 36 | Load the bin file and start the update. 37 | ![wifimanager_info](../images/wifi_manager_update_upload.png) 38 | 39 | Reboot board, upgrade completed! -------------------------------------------------------------------------------- /docs/sw_getting_started_blynk_iot.md: -------------------------------------------------------------------------------- 1 | # SW getting started Blynk LEGACY 2 | 3 | 4 | Blynk IOT requires *TEMPLATE_ID* to be defined at compilation time, for this reason, there's no pre-build firmware for it. 5 | 6 | Download/Clone this project, then, using Arduino IDE or VSC(Platformio) check the file named *config.h*. 7 | 8 | - Make sure `#define USE_BLYNK` is enabled/un-commented 9 | - Make sure `#define USE_BLYNK_2` is enabled/un-commented 10 | - Make sure `#define USE_MQTT` is disabled/commented 11 | - Insert your `BLYNK_TEMPLATE_ID` [blynk docs](https://docs.blynk.io/en/getting-started/activating-devices/manual-device-activation#step-2-getting-template-id) 12 | - Insert your `BLYNK_DEVICE_NAME` 13 | - Insert your `BLYNK_AUTH` [blynk docs](https://docs.blynk.io/en/getting-started/activating-devices/manual-device-activation#step-3-getting-auth-token) 14 | 15 | 16 | Compile the sketch and upload to your ESP module. 17 | -------------------------------------------------------------------------------- /docs/sw_getting_started_blynk_legacy.md: -------------------------------------------------------------------------------- 1 | # SW getting started Blynk LEGACY 2 | 3 | 4 | *!This sync should be consider as deprecated, as blynk IOT replaced it, you must have a working blynk (local) server!* 5 | 6 | Download the latest version of this firmware from [here](https://github.com/Bettapro/Solar-Tracer-Blynk-V3/releases/latest). 7 | Choose the correct bin file according to your board (esp8266, esp32): 8 | - *SolarTracerBlynk_xxxx_esp32dev_blynk.bin*: ESP32 only 9 | - *SolarTracerBlynk_xxxx_esp8266_blynk.bin*: ESP8266 only 10 | 11 | Flash the firmware on your EPS8266/ESP32, more information how to flash firmware are available [ESP32](esp32.md#how-to-flash) [ESP8266](esp8266.md#how-to-flash) 12 | 13 | ## Mobile App 14 | 15 | Get the Mobile App ([Android](https://www.apkmirror.com/apk/blynk-inc/blynk-legacy/blynk-legacy-2-27-34-release/blynk-legacy-2-27-34-android-apk-download/)) 16 | 17 | Open the Blynk mobile app and create a new project by scanning one of the following QR code. 18 | 19 | ### Legacy app (v3) - SUGGESTED 20 | Current version of the app, complete overview of the solar charge controller. ENERGY REQUIRED: 14300 21 | 22 | ![Project QR Code](../images/blynk-app-qr-code_v3_blynkcloud.png) 23 | 24 | ### Legacy app (v2) 25 | Original version of the mobile app, shows a small set of data. ENERGY REQUIRED: 4400 26 | 27 | ![Project QR Code](../images/blynk-app-qr-code.png) 28 | 29 | ## Back to ESP board 30 | 31 | Boot the ESP in Configuration mode and double check all the settings, double check the mqtt section and make sure that mqtt settings are correct. 32 | ![Alt text](../images/wifi_manager_config.png) 33 | 34 | That's all! your mobile app will get updated with the data from your SCC. 35 | 36 | ## Sample screenshot 37 | 38 | ![Realtime data screen v3](images/screenshot-blynk_v3_realtime.png) 39 | ![Battery data screen v3](images/screenshot-blynk_v3_battery.png) 40 | ![PV data screen v3](images/screenshot-blynk_v3_pv.png) 41 | ![Settings screen v3](images/screenshot-blynk_v3_settings.png) 42 | -------------------------------------------------------------------------------- /docs/sw_getting_started_ha.md: -------------------------------------------------------------------------------- 1 | # SW getting started Home Assistant 2 | 3 | *!You must have a working mqtt broker and also the mqtt integration in you home assistant integration!* 4 | 5 | Download the latest version of this firmware from [here](https://github.com/Bettapro/Solar-Tracer-Blynk-V3/releases/latest). 6 | Choose the correct bin file according to your board (esp8266, esp32): 7 | - *SolarTracerBlynk_xxxx_esp32dev_mqttHA.bin*: ESP32 only 8 | - *SolarTracerBlynk_xxxx_esp8266_mqttHA.bin*: ESP8266 only 9 | 10 | Flash the firmware on your EPS8266/ESP32, more information how to flash firmware are available [ESP32](esp32.md#how-to-flash) [ESP8266](esp8266.md#how-to-flash) 11 | 12 | 13 | Boot the ESP in Configuration mode and double check all the settings, double check the mqtt section and make sure that settings are correct. 14 | ![Alt text](../images/wifi_manager_mqtt_settings.png) 15 | 16 | If everything is working your mqtt integration will discover and configure the solar tracer. 17 | ![image](https://user-images.githubusercontent.com/3984840/160839821-8fd79592-4d98-4107-8b78-3d2c2c555c7f.png) 18 | 19 | ![image](https://user-images.githubusercontent.com/3984840/160840312-218e7718-c8e7-4236-bc88-470d8f4ea4ed.png) 20 | 21 | You can now proceed and display all the data you need on your widgets (and even on the Energy monitoring page!) 22 | ![image](https://user-images.githubusercontent.com/3984840/160840967-0c4d75c4-d63d-4e99-bd12-842cfa3c866f.png) 23 | ![image](https://user-images.githubusercontent.com/3984840/160841387-f500738a-e4a1-4b52-a2cd-69c78a732b52.png) 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/sw_getting_started_mqtt.md: -------------------------------------------------------------------------------- 1 | # SW getting started MQTT 2 | 3 | *!You must have a working mqtt broker!* 4 | 5 | Download the latest version of this firmware from [here](https://github.com/Bettapro/Solar-Tracer-Blynk-V3/releases/latest). 6 | Choose the correct bin file according to your board (esp8266, esp32): 7 | - *SolarTracerBlynk_xxxx_esp32dev_mqtt.bin*: ESP32 only 8 | - *SolarTracerBlynk_xxxx_esp8266_mqtt.bin*: ESP8266 only 9 | 10 | Flash the firmware on your EPS8266/ESP32, more information how to flash firmware are available [ESP32](esp32.md#how-to-flash) [ESP8266](esp8266.md#how-to-flash) 11 | 12 | 13 | Boot the ESP in Configuration mode and double check all the settings, double check the MQTT section and make sure that settings are correct. 14 | ![Alt text](../images/wifi_manager_mqtt_settings.png) 15 | 16 | On you MQTT broker you will find a new main topic named *solarTracer/values/* containing a topic for each value for your controller. 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /images/blynk-app-qr-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/blynk-app-qr-code.png -------------------------------------------------------------------------------- /images/blynk-app-qr-code_v3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/blynk-app-qr-code_v3.png -------------------------------------------------------------------------------- /images/blynk-app-qr-code_v3_blynkcloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/blynk-app-qr-code_v3_blynkcloud.png -------------------------------------------------------------------------------- /images/epever_rj45_specs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/epever_rj45_specs.png -------------------------------------------------------------------------------- /images/esp32_d1_mini_pins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/esp32_d1_mini_pins.png -------------------------------------------------------------------------------- /images/esp32_wroom_38_pin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/esp32_wroom_38_pin.jpg -------------------------------------------------------------------------------- /images/esp8266_bin_flash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/esp8266_bin_flash.png -------------------------------------------------------------------------------- /images/esp8266_hw_serial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/esp8266_hw_serial.png -------------------------------------------------------------------------------- /images/esp8266_sw_serial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/esp8266_sw_serial.png -------------------------------------------------------------------------------- /images/esp_tool_bin_flash_10000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/esp_tool_bin_flash_10000.png -------------------------------------------------------------------------------- /images/esp_tool_bin_flash_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/esp_tool_bin_flash_new.png -------------------------------------------------------------------------------- /images/esp_tool_board_select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/esp_tool_board_select.png -------------------------------------------------------------------------------- /images/eth_t568b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/eth_t568b.png -------------------------------------------------------------------------------- /images/max485_module.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/max485_module.jpg -------------------------------------------------------------------------------- /images/mppt-triton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/mppt-triton.png -------------------------------------------------------------------------------- /images/mppt-xtra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/mppt-xtra.png -------------------------------------------------------------------------------- /images/nodemcu_pins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/nodemcu_pins.png -------------------------------------------------------------------------------- /images/schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/schematic.png -------------------------------------------------------------------------------- /images/screenshot-blynk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/screenshot-blynk.png -------------------------------------------------------------------------------- /images/screenshot-blynk_v3_battery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/screenshot-blynk_v3_battery.png -------------------------------------------------------------------------------- /images/screenshot-blynk_v3_pv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/screenshot-blynk_v3_pv.png -------------------------------------------------------------------------------- /images/screenshot-blynk_v3_realtime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/screenshot-blynk_v3_realtime.png -------------------------------------------------------------------------------- /images/screenshot-blynk_v3_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/screenshot-blynk_v3_settings.png -------------------------------------------------------------------------------- /images/tracer-a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/tracer-a.png -------------------------------------------------------------------------------- /images/tracer-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/tracer-b.png -------------------------------------------------------------------------------- /images/wifi_manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/wifi_manager.png -------------------------------------------------------------------------------- /images/wifi_manager_config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/wifi_manager_config.png -------------------------------------------------------------------------------- /images/wifi_manager_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/wifi_manager_home.png -------------------------------------------------------------------------------- /images/wifi_manager_mqtt_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/wifi_manager_mqtt_settings.png -------------------------------------------------------------------------------- /images/wifi_manager_update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/wifi_manager_update.png -------------------------------------------------------------------------------- /images/wifi_manager_update_upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bettapro/Solar-Tracer-Blynk-V3/eb5d45b5a7472bf3e52c6d0c939759880faa9249/images/wifi_manager_update_upload.png -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [platformio] 12 | default_envs = esp32dev 13 | src_dir = SolarTracerBlynk 14 | 15 | [env] 16 | framework = arduino 17 | monitor_speed = 115200 18 | lib_deps = 19 | https://github.com/blynkkk/blynk-library.git#v1.1.0 20 | https://github.com/Bettapro/ModbusMaster.git 21 | https://github.com/schinken/SimpleTimer.git 22 | https://github.com/tzapu/WiFiManager.git#v2.0.17 23 | https://github.com/bblanchon/ArduinoJson.git 24 | knolleary/PubSubClient@^2.8 25 | https://github.com/dawidchyrzynski/arduino-home-assistant.git#2.1.0 26 | https://github.com/Bettapro/LinearSensHallCurrent.git 27 | https://github.com/RobTillaart/ADS1X15.git 28 | https://github.com/khoih-prog/ESP_DoubleResetDetector.git 29 | https://github.com/plerup/espsoftwareserial.git#8.2.0 30 | #build_type = debug 31 | build_flags = 32 | # stop first error 33 | -fmax-errors=1 34 | -DCORE_DEBUG_LEVEL=0 35 | #lib_ldf_mode = deep+ 36 | 37 | [extra] 38 | ota_hostname=SOLAR-MODBUS.local 39 | ota_password=admin 40 | 41 | [env:esp32dev] 42 | platform = espressif32 43 | board = esp32dev 44 | upload_speed = 460800 45 | monitor_filters = esp32_exception_decoder 46 | # OTA 47 | #upload_protocol = espota 48 | #upload_port = ${extra.ota_hostname} 49 | #upload_flags = --auth=${extra.ota_password} 50 | 51 | 52 | [env:esp8266] 53 | platform = espressif8266 54 | board = esp12e 55 | monitor_filters = esp8266_exception_decoder 56 | # OTA 57 | #upload_protocol = espota 58 | #upload_port = ${extra.ota_hostname} 59 | #upload_flags = --auth=${extra.ota_password} 60 | -------------------------------------------------------------------------------- /script/binDeploy.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | SETLOCAL EnableDelayedExpansion 3 | 4 | rmdir "binFiles" /S /Q 5 | 6 | set VERSION_number="3.0.9" 7 | 8 | set esp32_build_flag_base=-DUSE_HALL_AP_CONFIGURATION_TRIGGER 9 | set esp32_build_flag_minimum=-DUSE_NOT_BLYNK -DSTARTUP_BUILD 10 | set esp8266_build_flag_base= 11 | 12 | set buildRun[0].env=esp32dev 13 | set buildRun[0].fileSuffix=blynk 14 | set buildRun[0].buildFlags=%esp32_build_flag_base% 15 | 16 | set buildRun[1].env=esp32dev 17 | set buildRun[1].fileSuffix=mqtt 18 | set buildRun[1].buildFlags=%esp32_build_flag_base% -DUSE_NOT_BLYNK -DUSE_MQTT 19 | 20 | set buildRun[2].env=esp32dev 21 | set buildRun[2].fileSuffix=mqttHA 22 | set buildRun[2].buildFlags=%esp32_build_flag_base% -DUSE_NOT_BLYNK -DUSE_MQTT -DUSE_MQTT_HOME_ASSISTANT 23 | 24 | set buildRun[3].env=esp8266 25 | set buildRun[3].fileSuffix=blynk 26 | set buildRun[3].buildFlags=%esp8266_build_flag_base% 27 | 28 | set buildRun[4].env=esp8266 29 | set buildRun[4].fileSuffix=mqtt 30 | set buildRun[4].buildFlags=%esp8266_build_flag_base% -DUSE_NOT_BLYNK -DUSE_MQTT 31 | 32 | set buildRun[5].env=esp8266 33 | set buildRun[5].fileSuffix=mqttHA 34 | set buildRun[5].buildFlags=%esp8266_build_flag_base% -DUSE_NOT_BLYNK -DUSE_MQTT -DUSE_MQTT_HOME_ASSISTANT 35 | 36 | set buildRun[6].env=esp8266 37 | set buildRun[6].fileSuffix=blynk_swser 38 | set buildRun[6].buildFlags=%esp8266_build_flag_base% -DUSE_SOFTWARE_SERIAL 39 | 40 | set buildRun[7].env=esp8266 41 | set buildRun[7].fileSuffix=mqtt_swser 42 | set buildRun[7].buildFlags=%esp8266_build_flag_base% -DUSE_NOT_BLYNK -DUSE_MQTT -DUSE_SOFTWARE_SERIAL 43 | 44 | set buildRun[8].env=esp8266 45 | set buildRun[8].fileSuffix=mqttHA_swser 46 | set buildRun[8].buildFlags=%esp8266_build_flag_base% -DUSE_NOT_BLYNK -DUSE_MQTT -DUSE_MQTT_HOME_ASSISTANT -DUSE_SOFTWARE_SERIAL 47 | 48 | 49 | set esp32devEnv=esp32dev 50 | call set PLATFORMIO_BUILD_FLAGS=%esp32_build_flag_minimum% 51 | call %userprofile%\.platformio\penv\Scripts\pio.exe run -e %esp32devEnv% 52 | echo F| xcopy ".pio\build\%esp32devEnv%\firmware.bin" "binFiles\%esp32devEnv%\firmware.bin" /v /f /y 53 | echo F| xcopy ".pio\build\%esp32devEnv%\partitions.bin" "binFiles\%esp32devEnv%\partitions.bin" /v /f /y 54 | echo F| xcopy ".pio\build\%esp32devEnv%\bootloader.bin" "binFiles\%esp32devEnv%\bootloader.bin" /v /f /y 55 | echo F| xcopy "%userprofile%\.platformio\packages\framework-arduinoespressif32\tools\partitions\boot_app0.bin" "binFiles\%esp32devEnv%\boot_app0.bin" /v /f /y 56 | python script\esp32_binary_merger\merge_bin_esp.py --output_folder binFiles\ --output_name "SolarTracerBlynk_%VERSION_NUMBER%_%esp32devEnv%_0x0.bin" --bin_path "binFiles\%esp32devEnv%\bootloader.bin" "binFiles\%esp32devEnv%\partitions.bin" "binFiles\%esp32devEnv%\boot_app0.bin" "binFiles\%esp32devEnv%\firmware.bin" --bin_address 0x1000 0x8000 0xe000 0x10000 57 | 58 | set "x=0" 59 | 60 | :SymLoop 61 | if defined buildRun[%x%].env ( 62 | set currEnv=%%buildRun[%x%].env%% 63 | set currFileSuffix=%%buildRun[%x%].fileSuffix%% 64 | set currBuildFlags=%%buildRun[%x%].buildFlags%% 65 | call echo "ENV !currEnv! - file !currFileSuffix! - flag !currBuildFlags!" 66 | 67 | call set PLATFORMIO_BUILD_FLAGS=!currBuildFlags! 68 | rem call set PLATFORMIO_DEFAULT_ENVS=!currEnv! 69 | call %userprofile%\.platformio\penv\Scripts\pio.exe run -e !currEnv! 70 | 71 | call echo F| call xcopy ".pio\build\!currEnv!\firmware.bin" "binFiles\SolarTracerBlynk_%VERSION_NUMBER%_!currEnv!_!currFileSuffix!.bin" /v /f /y 72 | 73 | set /a "x+=1" 74 | GOTO :SymLoop 75 | ) 76 | -------------------------------------------------------------------------------- /script/binTest.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | SETLOCAL EnableDelayedExpansion 3 | 4 | rmdir "binFiles" /S /Q 5 | 6 | set esp32_build_flag_base=-DUSE_HALL_AP_CONFIGURATION_TRIGGER 7 | set esp8266_build_flag_base= 8 | 9 | 10 | set buildRun[0].env=esp32dev 11 | set buildRun[0].fileSuffix=run 12 | set buildRun[0].buildFlags=%esp32_build_flag_base% -DUSE_NOT_BLYNK -DUSE_MQTT -DUSE_MQTT_HOME_ASSISTANT -DUSE_EXTERNAL_HEAVY_LOAD_CURRENT_METER -DUSE_HALL_AP_CONFIGURATION_TRIGGER 13 | 14 | 15 | set "x=0" 16 | 17 | :SymLoop 18 | if defined buildRun[%x%].env ( 19 | set currEnv=%%buildRun[%x%].env%% 20 | set currFileSuffix=%%buildRun[%x%].fileSuffix%% 21 | set currBuildFlags=%%buildRun[%x%].buildFlags%% 22 | call echo "ENV !currEnv! - file !currFileSuffix! - flag !currBuildFlags!" 23 | 24 | call set PLATFORMIO_BUILD_FLAGS=!currBuildFlags! 25 | rem call set PLATFORMIO_DEFAULT_ENVS=!currEnv! 26 | call %userprofile%\.platformio\penv\Scripts\pio.exe run -e !currEnv! 27 | call echo F| call xcopy ".pio\build\!currEnv!\firmware.bin" "binFiles\SolarTracerBlynk_!currEnv!_!currFileSuffix!.bin" /v /f /y 28 | 29 | set /a "x+=1" 30 | GOTO :SymLoop 31 | ) 32 | -------------------------------------------------------------------------------- /script/esp32_binary_merger/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Tony Martinet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /script/esp32_binary_merger/merge_bin_esp.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | 4 | class bin(): 5 | def __init__(self, file_path, addr): 6 | self.file_path = file_path 7 | self.file_name = os.path.basename(file_path) 8 | self.addr = addr 9 | self.size = self.get_size() 10 | 11 | def get_size(self): 12 | return int(os.path.getsize(self.file_path)) 13 | 14 | class multiple_bin(): 15 | def __init__(self, name, output_folder): 16 | self.name = name 17 | self.output_folder = output_folder 18 | try: 19 | os.makedirs(os.path.realpath(self.output_folder)) 20 | except: 21 | pass 22 | self.output_path = os.path.realpath(os.path.join(self.output_folder,self.name)) 23 | self.bin_array = [] 24 | 25 | def add_bin(self, file_path, addr): 26 | self.bin_array.append(bin(file_path, addr)) 27 | 28 | def sort_bin(self): 29 | swapped = True 30 | while swapped: 31 | swapped = False 32 | for i in range(len(self.bin_array) - 1): 33 | if self.bin_array[i].addr > self.bin_array[i + 1].addr: 34 | self.bin_array[i], self.bin_array[i + 1] = self.bin_array[i + 1], self.bin_array[i] 35 | swapped = True 36 | 37 | def add_bin_to_other_bin(self, previous, binary): 38 | with open(self.output_path, "ab") as output_file: 39 | output_file.write( b'\xff' * (binary.addr-previous)) 40 | print ("Add %s from 0x%x to 0x%x (0x%x)"%(binary.file_name, binary.addr, binary.addr+binary.size, binary.size)) 41 | with open(self.output_path, "ab") as output_file, open(binary.file_path, "rb") as bin_file: 42 | output_file.write(bin_file.read()) 43 | return binary.addr+binary.size 44 | 45 | def create_bin(self): 46 | new_start = 0 47 | open(self.output_path, "wb").close 48 | for b in self.bin_array: 49 | new_start = self.add_bin_to_other_bin(new_start, b) 50 | 51 | def check_if_possible(self): 52 | for i in range(1, len(self.bin_array)): 53 | if(self.bin_array[i].addr < (self.bin_array[i-1].addr+self.bin_array[i-1].size)): 54 | print (self.bin_array[i].addr, (self.bin_array[i-1].addr+self.bin_array[i-1].size)) 55 | raise Exception("Not possible to create this bin, overlapping between %s and %s"%(self.bin_array[i].file_name, self.bin_array[i-1].file_name)) 56 | 57 | def main(): 58 | parser = argparse.ArgumentParser(description='Script to merge *.bin file at different position') 59 | parser.add_argument( 60 | '--output_name', 61 | help = 'Output file name', default = "output.bin") 62 | parser.add_argument( 63 | '--output_folder', default = "output", 64 | help = 'Output folder path') 65 | parser.add_argument( 66 | '--input_folder', default = "", 67 | help = 'Input folder path') 68 | parser.add_argument( 69 | '--bin_path',nargs='+',required=True, 70 | help = 'List of bin path, same order as bin_address (space separated)') 71 | parser.add_argument( 72 | '--bin_address',nargs='+',type=lambda x: int(x,0),required=True, 73 | help = 'List of addr, same order as bin_path (space separated)') 74 | parser.add_argument 75 | args = parser.parse_args() 76 | mb = multiple_bin(args.output_name, args.output_folder) 77 | for path,address in zip(args.bin_path, args.bin_address): 78 | mb.add_bin(os.path.join(args.input_folder, path), address) 79 | mb.sort_bin() 80 | mb.check_if_possible() 81 | mb.create_bin() 82 | print ("%s generated with success ! (size %u)"%(args.output_name, int(os.path.getsize(mb.output_path)))) 83 | 84 | if __name__ == "__main__": 85 | exit(main()) 86 | --------------------------------------------------------------------------------