diff --git a/.github/workflows/compile_development.yml b/.github/workflows/compile_development.yml index 59460d5c..ffde2d21 100644 --- a/.github/workflows/compile_development.yml +++ b/.github/workflows/compile_development.yml @@ -47,7 +47,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d src --environment esp8266-release --environment esp8266-release-prometheus --environment esp8285-release --environment esp32-wroom32-release --environment esp32-wroom32-release-prometheus + run: pio run -d src --environment esp8266-release --environment esp8266-release-prometheus --environment esp8285-release --environment esp32-wroom32-release --environment esp32-wroom32-release-prometheus --environment opendtufusionv1-release - name: Rename Binary files id: rename-binary-files diff --git a/.github/workflows/compile_release.yml b/.github/workflows/compile_release.yml index bd7cef5a..84ad5111 100644 --- a/.github/workflows/compile_release.yml +++ b/.github/workflows/compile_release.yml @@ -51,7 +51,7 @@ jobs: run: python convert.py - name: Run PlatformIO - run: pio run -d src --environment esp8266-release --environment esp8266-release-prometheus --environment esp8285-release --environment esp32-wroom32-release --environment esp32-wroom32-release-prometheus + run: pio run -d src --environment esp8266-release --environment esp8266-release-prometheus --environment esp8285-release --environment esp32-wroom32-release --environment esp32-wroom32-release-prometheus --environment opendtufusionv1-release - name: Rename Binary files id: rename-binary-files diff --git a/.gitignore b/.gitignore index d6a35860..2ee4b679 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ src/web/html/tmp/* *.db *.suo *.ipch +src/output.map diff --git a/Getting_Started.md b/Getting_Started.md index ff592f8b..e73277f0 100644 --- a/Getting_Started.md +++ b/Getting_Started.md @@ -1,3 +1,22 @@ +## Overview + +This page describes how the module of a Wemos D1 mini and ESP8266 is wired to the radio module and is flashed with the latest Firmware.
+Further information will help you to communicate to the compatible inverters. + +You find the full [User_Manual here](User_Manual.md) + +## Compatiblity + +For now the following Inverters should work out of the box: + +Hoymiles Inverters + +| Status | Serie | Model | comment | +| ----- | ----- | ------ | ------- | +| ✔️ | MI | 300, 600, 1000/1200/⚠️ 1500 | 4-Channel is not tested yet | +| ✔️ | HM | 300, 350, 400, 600, 700, 800, 1000?, 1200, 1500 | | +| ⚠️ | TSUN | [TSOL-M350](https://www.tsun-ess.com/Micro-Inverter/M350-M400), [TSOL-M400](https://www.tsun-ess.com/Micro-Inverter/M350-M400), [TSOL-M800/TSOL-M800(DE)](https://www.tsun-ess.com/Micro-Inverter/M800) | others may work as well (need to be verified). | + ## Table of Contents - [Table of Contents](#table-of-contents) @@ -26,45 +45,10 @@ - [HTTP based Pages](#http-based-pages) - [MQTT command to set the DTU without webinterface](#mqtt-command-to-set-the-dtu-without-webinterface) - [Used Libraries](#used-libraries) -- [Contact](#contact) - [ToDo](#todo) *** -## Overview - -This page describes how the module of a Wemos D1 mini and ESP8266 is wired to the radio module and is flashed with the latest Firmware.
-Further information will help you to communicate to the compatible inverters. - -You find the full [User_Manual here](User_Manual.md) - -## Compatiblity - -For now the following Inverters should work out of the box: - -Hoymiles Inverters - -- HM300 -- HM350 -- HM400 -- HM600 -- HM700 -- HM800 -- HM1000? -- HM1200 -- HM1500 -- MI-300* [For MI inverters see remarks here](User_Manual.md#mi-inverters) -- MI-600* -- MI-700* -- MI-1500* (2nd gen. still untested) - -TSUN Inverters: - -- [TSOL-M350](https://www.tsun-ess.com/Micro-Inverter/M350-M400) -- [TSOL-M400](https://www.tsun-ess.com/Micro-Inverter/M350-M400) -- [TSOL-M800/TSOL-M800(DE)](https://www.tsun-ess.com/Micro-Inverter/M800) -- others may work as well (need to be verified). - Solenso Inverters: - SOL-H350 @@ -178,12 +162,27 @@ CE D2 (GPIO4) IRQ D0 (GPIO16 - no IRQ!) ``` +ATTENTION: From development version 108 onwards, also MISO, MOSI and SCLK +are configurable. Their defaults are correct for 'standard' ESP32 boards +and non-settable for ESP8266 (as this chip cannot move them elsewhere). +If you have an existing install though, you might see '0' in the web GUI. + +Set MISO=19, MOSI=23, SCLK=18 in GUI and save for existing installs, this is the old +correct default for most ESP32 boards, for ESP82xx, a simple settings save should suffice. +Reboot afterwards. + + ## Flash the Firmware on your Ahoy DTU Hardware Once your Hardware is ready to run, you need to flash the Ahoy DTU Firmware to your Board. You can either build your own using your own configuration or use one of our pre-compiled generic builds. -#### Compiling your own Version +### Flash from your browser (easy) + +The easiest step for you is to flash online. A browser MS Edge or Google Chrome is required. +[Here you go](https://ahoydtu.de/web_install/) + +### Compiling your own Version This information suits you if you want to configure and build your own firmware. @@ -292,12 +291,6 @@ When everything is wired up and the firmware is flashed, it is time to connect t | `ArduinoJson` | 6.19.4 | MIT | | `ESP Async WebServer` | 4.3.0 | ? | -## Contact - -We run a Discord Server that can be used to get in touch with the Developers and Users. - - - ## ToDo [See this post](https://github.com/lumapu/ahoy/issues/142) diff --git a/README.md b/README.md index b7e2aa9e..ab91e178 100644 --- a/README.md +++ b/README.md @@ -18,23 +18,27 @@ This work is licensed under a **Communicate with Hoymiles inverters via radio**. Get actual values like power, current, daily energy and set parameters like the power limit via web interface or MQTT. In this repository you will find different approaches means Hardware / Software to realize the described functionalities. -List of approaches +Table of approaches: -- [ESP8266/ESP32, C++](Getting_Started.md) 👈 the most effort is spent here -- [Arduino Nano, C++](tools/nano/NRF24_SendRcv/) -- [Raspberry Pi, Python](tools/rpi/) -- [Others, C/C++](tools/nano/NRF24_SendRcv/) +| Board | MI | HM | HMS/HMT | comment | HowTo start | +| ------ | -- | -- | ------- | ------- | ---------- | +| [ESP8266/ESP32, C++](Getting_Started.md) | ✔️ | ✔️ | coming soon✨ | 👈 the most effort is spent here | [create your own DTU](https://ahoydtu.de/getting_started/) | +| [Arduino Nano, C++](tools/nano/NRF24_SendRcv/) | ❌ | ✔️ | ❌ | | +| [Raspberry Pi, Python](tools/rpi/) | ❌ | ✔️ | ❌ | | +| [Others, C/C++](tools/nano/NRF24_SendRcv/) | ❌ | ✔️ | ❌ | | -## Quick Start with ESP8266 -- [Go here ✨](Getting_Started.md#things-needed) -- [Our Website](https://ahoydtu.de) +## Getting Started +[Guide how to start with a ESP module](Getting_Started.md) +[ESP Webinstaller (Edge / Chrome Browser only)](https://ahoydtu.de/web_install) +## Our Website +[https://ahoydtu.de](https://ahoydtu.de) ## Success Stories - [Getting the data into influxDB and visualize them in a Grafana Dashboard](https://grafana.com/grafana/dashboards/16850-pv-power-ahoy/) (thx @Carl) ## Support, Feedback, Information and Discussion -- [Discord Server (~ 1200 Users)](https://discord.gg/WzhxEY62mB) +- [Discord Server (~ 3.800 Users)](https://discord.gg/WzhxEY62mB) - [The root of development](https://www.mikrocontroller.net/topic/525778) ### Development diff --git a/scripts/getVersion.py b/scripts/getVersion.py index 77c5816b..0ebe1ec2 100644 --- a/scripts/getVersion.py +++ b/scripts/getVersion.py @@ -78,6 +78,11 @@ def readVersion(path, infile): dst = path + "firmware/" + versionout os.rename(src, dst) + versionout = version[:-1] + "_" + sha + "_esp32s3.bin" + src = path + ".pio/build/opendtufusionv1-release/firmware.bin" + dst = path + "firmware/" + versionout + os.rename(src, dst) + # other ESP32 bin files src = path + ".pio/build/esp32-wroom32-release/" dst = path + "firmware/" diff --git a/src/.vscode/settings.json b/src/.vscode/settings.json index c0becfd1..58a2c3c7 100644 --- a/src/.vscode/settings.json +++ b/src/.vscode/settings.json @@ -4,20 +4,16 @@ "workbench.colorCustomizations": { "editorLineNumber.foreground": "#00ff00" }, - "editor.wordWrap": "off", - "files.eol" : "\n", - "files.trimTrailingWhitespace" : true, - + "files.eol": "\n", + "files.trimTrailingWhitespace": true, "diffEditor.ignoreTrimWhitespace": true, "files.autoSave": "afterDelay", - "editor.tabSize": 4, "editor.insertSpaces": true, // `editor.tabSize` and `editor.insertSpaces` will be detected based on the file contents. // Set to false to keep the values you've explicitly set, above. "editor.detectIndentation": false, - // https://clang.llvm.org/docs/ClangFormatStyleOptions.html "C_Cpp.clang_format_fallbackStyle": "{ BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 0}", "files.associations": { @@ -86,4 +82,5 @@ "thread": "cpp" }, "cmake.configureOnOpen": false, + "editor.formatOnSave": false, } \ No newline at end of file diff --git a/src/CHANGES.md b/src/CHANGES.md index 7c58866a..debcf40d 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,253 +1,33 @@ -# Changelog +Changelog v0.6.0 -(starting from release version `0.5.66`) +## General +* improved night time calculation time to 1 minute after last communication pause #515 +* refactored code for better readability +* improved Hoymiles commuinication (retransmits, immediate power limit transmission, timing at all) +* renamed firmware binaries +* add login / logout to menu +* add display support for `SH1106`, `SSD1306`, `Nokia` and `ePaper 1.54"` (ESP32 only) +* add yield total correction - move your yield to a new inverter or correct an already used inverter +* added import / export feature +* added `Prometheus` endpoints +* improved wifi connection and stability (connect to strongest AP) +* addded Hoymiles alarm IDs to log +* improved `System` information page (eg. radio statitistics) +* improved UI (repsonsive design, (optional) dark mode) +* improved system stability (reduced `heap-fragmentation`, don't break settings on failure) #644, #645 +* added support for 2nd generation of Hoymiles inverters, MI series +* improved JSON API for more stable WebUI +* added option to disable input display in `/live` (`max-power` has to be set to `0`) +* updated documentation +* improved settings on ESP32 devices while setting SPI pins (for `NRF24` radio) -## 0.5.107 -* fix: show save message -* fix: removed serial newline for `enqueueCmd` -* Merged improved Prometheus #808 - -## 0.5.106 -* merged MI and debug message changes #804 -* fixed MQTT autodiscover #794, #632 - -## 0.5.105 -* merged MI, thx @rejoe2 #788 -* fixed reboot message #793 - -## 0.5.104 -* further improved save settings -* removed `#` character from ePaper -* fixed saving pinout for `Nokia-Display` -* removed `Reset` Pin for monochrome displays -* improved wifi connection #652 - -## 0.5.103 -* merged MI improvements, thx @rejoe2 #778 -* changed display inverter online message -* merged heap improvements #772 - -## 0.5.102 -* Warning: old exports are not compatible any more! -* fix JSON import #775 -* fix save settings, at least already stored settings are not lost #771 -* further save settings improvements (only store inverters which are existing) -* improved display of settings save return value -* made save settings asynchronous (more heap memory is free) - -## 0.5.101 -* fix SSD1306 -* update documentation -* Update miPayload.h -* Update README.md -* MI - remarks to user manual -* MI - fix AC calc -* MI - fix status msg. analysis - -## 0.5.100 -* fix add inverter `setup.html` #766 -* fix MQTT retained flag for total values #726 -* renamed buttons for import and export `setup.html` -* added serial message `settings saved` - -## 0.5.99 -* fix limit in [User_Manual.md](../User_Manual.md) -* changed `contrast` to `luminance` in `setup.html` -* try to fix SSD1306 display #759 -* only show necessary display pins depending on setting - -## 0.5.98 -* fix SH1106 rotation and turn off during night #756 -* removed MQTT subscription `sync_ntp`, `set_time` with a value of `0` does the same #696 -* simplified MQTT subscription for `limit`. Check [User_Manual.md](../User_Manual.md) for new syntax #696, #713 -* repaired inverter wise limit control -* fix upload settings #686 - -## 0.5.97 -* Attention: re-ordered display types, check your settings! #746 -* improved saving settings of display #747, #746 -* disabled contrast for Nokia display #746 -* added Prometheus as compile option #719, #615 -* update MQTT lib to v1.4.1 -* limit decimal places to 2 in `live` -* added `-DPIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48` to esp8266 debug build #657 -* a `max-module-power` of `0` disables channel in live view `setup` -* merge MI improvements, get firmware information #753 - -## 0.5.96 -* added Nokia display again for ESP8266 #764 -* changed `var` / `VAr` to SI unit `var` #732 -* fix MQTT retained flags for totals (P_AC, P_DC) #726, #721 - -## 0.5.95 -* merged #742 MI Improvments -* merged #736 remove obsolete JSON Endpoint - -## 0.5.94 -* added ePaper (for ESP32 only!), thx @dAjaY85 #735 -* improved `/live` margins #732 -* renamed `var` to `VAr` #732 - -## 0.5.93 -* improved web API for `live` -* added dark mode option -* converted all forms to reponsive design -* repaired menu with password protection #720, #716, #709 -* merged MI series fixes #729 - -## 0.5.92 -* fix mobile menu -* fix inverters in select `serial.html` #709 - -## 0.5.91 -* improved html and navi, navi is visible even when API dies #660 -* reduced maximum allowed JSON size for API to 6000Bytes #660 -* small fix: output command at `prepareDevInformCmd` #692 -* improved inverter handling #671 - -## 0.5.90 -* merged PR #684, #698, #705 -* webserial minor overflow fix #660 -* web `index.html` improve version information #701 -* fix MQTT sets power limit to zero (0) #692 -* changed `reset at midnight` with timezone #697 - -## 0.5.89 -* reduced heap fragmentation (removed `strtok` completely) #644, #645, #682 -* added part of mac address to MQTT client ID to seperate multiple ESPs in same network -* added dictionary for MQTT to reduce heap-fragmentation -* removed `last Alarm` from Live view, because it showed always the same alarm - will change in future - -## 0.5.88 -* MQTT Yield Day zero, next try to fix #671, thx @beegee3 -* added Solenso inverter to supported devices -* improved reconnection of MQTT #650 - -## 0.5.87 -* fix yield total correction as module (inverter input) value #570 -* reneabled instant start communication (once NTP is synced) #674 - -## 0.5.86 -* prevent send devcontrol request during disabled night communication -* changed yield total correction as module (inverter input) value #570 -* MQTT Yield Day zero, next try to fix #671 - -## 0.5.85 -* fix power-limit was not checked for max retransmits #667 -* fix blue LED lights up all the time #672 -* fix installing schedulers if NTP server isn't available -* improved zero values on triggers #671 -* hardcoded MQTT subtopics, because wildcard `#` leads to errors -* rephrased some messages on webif, thx to @Argafal #638 -* fixed 'polling stop message' on `index.html` #639 - -## 0.5.84 -* fix blue LED lights up all the time #672 -* added an instant start communication (once NTP is synced) -* add MI 3rd generation inverters (10x2 serial numbers) -* first decodings of messages from MI 2nd generation inverters - -## 0.5.83 -* fix MQTT publishing, `callback` was set but reset by following `setup()` - -## 0.5.82 -* fixed communication error #652 -* reset values is no bound to MQTT any more, setting moved to `inverter` #649 -* fixed wording on `index.hmtl` #661 - -## 0.5.81 -* started implementation of MI inverters (setup.html, own processing `MiPayload.h`) - -## 0.5.80 -* fixed communication #656 - -## 0.5.79 -* fixed mixed reset flags #648 -* fixed `mCbAlarm` if MQTT is not used #653 -* fixed MQTT `autodiscover` #630 thanks to @antibill51 -* next changes from @beegee many thanks for your contribution! -* replaced `CircularBuffer` by `std::queue` -* reworked `hmRadio.h` completely (interrupts, packaging) -* fix exception while `reboot` -* cleanup MQTT coding - -## 0.5.78 -* further improvements regarding wifi #611, fix connection if only one AP with same SSID is there -* fix endless loop in `zerovalues` #564 -* fix auto discover again #565 -* added total values to autodiscover #630 -* improved zero at midnight #625 - -## 0.5.77 -* fix wrong filename for automatically created manifest (online installer) #620 -* added rotate display feature #619 -* improved Prometheus endpoint #615, thx to @fsck-block -* improved wifi to connect always to strongest RSSI, thx to @beegee3 #611 - -## 0.5.76 -* reduce MQTT retry interval from maximum speed to one second -* fixed homeassistant autodiscovery #565 -* implemented `getNTPTime` improvements #609 partially #611 -* added alarm messages to MQTT #177, #600, #608 - -## 0.5.75 -* fix wakeup issue, once wifi was lost during night the communication didn't start in the morning -* reenabled FlashStringHelper because of lacking RAM -* complete rewrite of monochrome display class, thx to @dAjaY85 -> displays are now configurable in setup -* fix power limit not possible #607 - -## 0.5.74 -* improved payload handling (retransmit all fragments on CRC error) -* improved `isAvailable`, checkes all record structs, inverter becomes available more early because version is check first -* fix tickers were not set if NTP is not available -* disabled annoying `FlashStringHelper` it gives randomly Expeptions during development, feels more stable since then -* moved erase button to the bottom in settings, not nice but more functional -* split `tx_count` to `tx_cnt` and `retransmits` in `system.html` -* fix mqtt retransmit IP address #602 -* added debug infos for `scheduler` (web -> `/debug` as trigger prints list of tickers to serial console) - -## 0.5.73 -* improved payload handling (request / retransmit) #464 -* included alarm ID parse to serial console (in development) - -## 0.5.72 -* repaired system, scheduler was not called any more #596 - -## 0.5.71 -* improved wifi handling and tickers, many thanks to @beegee3 #571 -* fixed YieldTotal correction calculation #589 -* fixed serial output of power limit acknowledge #569 -* reviewed `sendDiscoveryConfig` #565 -* merged PR `Monodisplay`, many thanks to @dAjaY85 #566, Note: (settings are introduced but not able to be modified, will be included in next version) - -## 0.5.70 -* corrected MQTT `comm_disabled` #529 -* fix Prometheus and JSON endpoints (`config_override.h`) #561 -* publish MQTT with fixed interval even if inverter is not available #542 -* added JSON settings upload. NOTE: settings JSON download changed, so only settings should be uploaded starting from version `0.5.70` #551 -* MQTT topic and inverter name have more allowed characters: `[A-Za-z0-9./#$%&=+_-]+`, thx: @Mo Demman -* improved potential issue with `checkTicker`, thx @cbscpe -* MQTT option for reset values on midnight / not avail / communication stop #539 -* small fix in `tickIVCommunication` #534 -* add `YieldTotal` correction, eg. to have the option to zero at year start #512 - -## 0.5.69 -* merged SH1106 1.3" Display, thx @dAjaY85 -* added SH1106 to automatic build -* added IP address to MQTT (version, device and IP are retained and only transmitted once after boot) #556 +## MqTT +* added `comm_disabled` #529 +* added fixed interval option #542, #523 +* improved communication, only required publishes +* improved retained flags * added `set_power_limit` acknowledge MQTT publish #553 -* changed: version, device name are only published via MQTT once after boot -* added `Login` to menu if admin password is set #554 -* added `development` to second changelog link in `index.html` #543 -* added interval for MQTT (as option). With this settings MQTT live data is published in a fixed timing (only if inverter is available) #542, #523 -* added MQTT `comm_disabled` #529 -* changed name of binaries, moved GIT-Sha to the front #538 - -## 0.5.68 -* repaired receive payload -* Powerlimit is transfered immediately to inverter - -## 0.5.67 -* changed calculation of start / stop communication to 1 min after last comm. stop #515 -* moved payload send to `payload.h`, function `ivSend` #515 -* payload: if last frame is missing, request all frames again +* added feature to reset values on midnight, communication pause or if the inverters are not available +* partially added Hoymiles alarm ID +* improved autodiscover (added total values on multi-inverter setup) +* improved `clientID` a part of the MAC address is added to have an unique name diff --git a/src/app.cpp b/src/app.cpp index 23030d76..d3fba12a 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -30,9 +30,9 @@ void app::setup() { DBGPRINTLN(F("false")); mSys.enableDebug(); - mSys.setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); + mSys.setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs, mConfig->nrf.pinSclk, mConfig->nrf.pinMosi, mConfig->nrf.pinMiso); - #if defined(AP_ONLY) +#if defined(AP_ONLY) mInnerLoopCb = std::bind(&app::loopStandard, this); #else mInnerLoopCb = std::bind(&app::loopWifi, this); diff --git a/src/config/config.h b/src/config/config.h index 5bb085f4..ac28c1a2 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -44,13 +44,25 @@ // default pinout (GPIO Number) #if defined(ESP32) + // this is the default ESP32 (son-S) pinout on the WROOM modules for VSPI, + // for the ESP32-S3 there is no sane 'default', as it has full flexibility + // to map its two HW SPIs anywhere and PCBs differ materially, + // so it has to be selected in the Web UI #define DEF_CS_PIN 5 #define DEF_CE_PIN 4 #define DEF_IRQ_PIN 16 + #define DEF_MISO_PIN 19 + #define DEF_MOSI_PIN 23 + #define DEF_SCLK_PIN 18 #else #define DEF_CS_PIN 15 #define DEF_CE_PIN 2 #define DEF_IRQ_PIN 0 + // these are given to relay the correct values via API + // they cannot actually be moved for ESP82xx models + #define DEF_MISO_PIN 12 + #define DEF_MOSI_PIN 13 + #define DEF_SCLK_PIN 14 #endif // default NRF24 power, possible values (0 - 3) diff --git a/src/config/config_override_example.h b/src/config/config_override_example.h index ed976ceb..e7c06b77 100644 --- a/src/config/config_override_example.h +++ b/src/config/config_override_example.h @@ -17,14 +17,19 @@ #undef FB_WIFI_PWD #define FB_WIFI_PWD "MY_WIFI_KEY" -// ESP32 default pinout -#undef DEF_RF24_CS_PIN -#define DEF_RF24_CS_PIN 5 -#undef DEF_RF24_CE_PIN -#define DEF_RF24_CE_PIN 4 -#undef DEF_RF24_IRQ_PIN -#define DEF_RF24_IRQ_PIN 16 - +// ESP32-S3 example pinout +#undef DEF_CS_PIN +#define DEF_CS_PIN 37 +#undef DEF_CE_PIN +#define DEF_CE_PIN 38 +#undef DEF_IRQ_PIN +#define DEF_IRQ_PIN 47 +#undef DEF_MISO_PIN +#define DEF_MISO_PIN 48 +#undef DEF_MOSI_PIN +#define DEF_MOSI_PIN 35 +#undef DEF_SCLK_PIN +#define DEF_SCLK_PIN 36 // Offset for midnight Ticker Example: 1 second before midnight (local time) #undef MIDNIGHTTICKER_OFFSET diff --git a/src/config/settings.h b/src/config/settings.h index a1c5a85f..6d58b406 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -73,6 +73,9 @@ typedef struct { uint8_t pinCs; uint8_t pinCe; uint8_t pinIrq; + uint8_t pinMiso; + uint8_t pinMosi; + uint8_t pinSclk; uint8_t amplifierPower; } cfgNrf24_t; @@ -344,6 +347,10 @@ class settings { mCfg.nrf.pinCs = DEF_CS_PIN; mCfg.nrf.pinCe = DEF_CE_PIN; mCfg.nrf.pinIrq = DEF_IRQ_PIN; + mCfg.nrf.pinMiso = DEF_MISO_PIN; + mCfg.nrf.pinMosi = DEF_MOSI_PIN; + mCfg.nrf.pinSclk = DEF_SCLK_PIN; + mCfg.nrf.amplifierPower = DEF_AMPLIFIERPOWER & 0x03; snprintf(mCfg.ntp.addr, NTP_ADDR_LEN, "%s", DEF_NTP_SERVER_NAME); @@ -426,6 +433,9 @@ class settings { obj[F("cs")] = mCfg.nrf.pinCs; obj[F("ce")] = mCfg.nrf.pinCe; obj[F("irq")] = mCfg.nrf.pinIrq; + obj[F("sclk")] = mCfg.nrf.pinSclk; + obj[F("mosi")] = mCfg.nrf.pinMosi; + obj[F("miso")] = mCfg.nrf.pinMiso; obj[F("pwr")] = mCfg.nrf.amplifierPower; } else { mCfg.nrf.sendInterval = obj[F("intvl")]; @@ -433,11 +443,17 @@ class settings { mCfg.nrf.pinCs = obj[F("cs")]; mCfg.nrf.pinCe = obj[F("ce")]; mCfg.nrf.pinIrq = obj[F("irq")]; + mCfg.nrf.pinSclk = obj[F("sclk")]; + mCfg.nrf.pinMosi = obj[F("mosi")]; + mCfg.nrf.pinMiso = obj[F("miso")]; mCfg.nrf.amplifierPower = obj[F("pwr")]; if((obj[F("cs")] == obj[F("ce")])) { - mCfg.nrf.pinCs = DEF_CS_PIN; - mCfg.nrf.pinCe = DEF_CE_PIN; - mCfg.nrf.pinIrq = DEF_IRQ_PIN; + mCfg.nrf.pinCs = DEF_CS_PIN; + mCfg.nrf.pinCe = DEF_CE_PIN; + mCfg.nrf.pinIrq = DEF_IRQ_PIN; + mCfg.nrf.pinSclk = DEF_SCLK_PIN; + mCfg.nrf.pinMosi = DEF_MOSI_PIN; + mCfg.nrf.pinMiso = DEF_MISO_PIN; } } } diff --git a/src/defines.h b/src/defines.h index 05cbd23b..1be438ff 100644 --- a/src/defines.h +++ b/src/defines.h @@ -12,8 +12,8 @@ // VERSION //------------------------------------- #define VERSION_MAJOR 0 -#define VERSION_MINOR 5 -#define VERSION_PATCH 107 +#define VERSION_MINOR 6 +#define VERSION_PATCH 0 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index d3efd9ac..b1390b29 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -304,7 +304,7 @@ class Inverter { if (getPosByChFld(0, FLD_ACT_ACTIVE_PWR_LIMIT, rec) == pos){ actPowerLimit = rec->record[pos]; DPRINT(DBG_DEBUG, F("Inverter actual power limit: ")); - DBGPRINTLN(String(actPowerLimit, 1)); + DPRINTLN(DBG_DEBUG, String(actPowerLimit, 1)); } } else if (rec->assign == AlarmDataAssignment) { diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index 01282b00..0af8f466 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -168,7 +168,7 @@ class HmPayload { DPRINTLN(DBG_DEBUG, F("fragment number zero received and ignored")); } else { DPRINT(DBG_DEBUG, F("PID: 0x")); - DBGHEXLN(*pid); + DPRINTLN(DBG_DEBUG, String(*pid, HEX)); if ((*pid & 0x7F) < MAX_PAYLOAD_ENTRIES) { memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->packet[10], p->len - 11); mPayload[iv->id].len[(*pid & 0x7F) - 1] = p->len - 11; @@ -285,7 +285,7 @@ class HmPayload { DPRINT(DBG_INFO, F("procPyld: txid: 0x")); DBGHEXLN(mPayload[iv->id].txId); DPRINT(DBG_DEBUG, F("procPyld: max: ")); - DBGPRINTLN(String(mPayload[iv->id].maxPackId)); + DPRINTLN(DBG_DEBUG, String(mPayload[iv->id].maxPackId)); record_t<> *rec = iv->getRecordStruct(mPayload[iv->id].txCmd); // choose the parser mPayload[iv->id].complete = true; diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index a9564196..c37ab7d0 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -10,6 +10,7 @@ #include #include "../utils/crc.h" #include "../config/config.h" +#include "SPI.h" #define SPI_SPEED 1000000 @@ -47,7 +48,7 @@ const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"}; //----------------------------------------------------------------------------- // HM Radio class //----------------------------------------------------------------------------- -template +template class HmRadio { public: HmRadio() : mNrf24(CE_PIN, CS_PIN, SPI_SPEED) { @@ -78,7 +79,7 @@ class HmRadio { } ~HmRadio() {} - void setup(uint8_t ampPwr = RF24_PA_LOW, uint8_t irq = IRQ_PIN, uint8_t ce = CE_PIN, uint8_t cs = CS_PIN) { + void setup(uint8_t ampPwr = RF24_PA_LOW, uint8_t irq = IRQ_PIN, uint8_t ce = CE_PIN, uint8_t cs = CS_PIN, uint8_t sclk = SCLK_PIN, uint8_t mosi = MOSI_PIN, uint8_t miso = MISO_PIN) { DPRINTLN(DBG_VERBOSE, F("hmRadio.h:setup")); pinMode(irq, INPUT_PULLUP); @@ -100,7 +101,19 @@ class HmRadio { // change the byte order of the DTU serial number and append the required 0x01 at the end DTU_RADIO_ID = ((uint64_t)(((dtuSn >> 24) & 0xFF) | ((dtuSn >> 8) & 0xFF00) | ((dtuSn << 8) & 0xFF0000) | ((dtuSn << 24) & 0xFF000000)) << 8) | 0x01; - mNrf24.begin(ce, cs); + #ifdef ESP32 + #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 + mSpi = new SPIClass(FSPI); + #else + mSpi = new SPIClass(VSPI); + #endif + mSpi->begin(sclk, miso, mosi, cs); + #else + //the old ESP82xx cannot freely place their SPI pins + mSpi = new SPIClass(); + mSpi->begin(); + #endif + mNrf24.begin(mSpi, ce, cs); mNrf24.setRetries(3, 15); // 3*250us + 250us and 15 loops -> 15ms mNrf24.setChannel(mRfChLst[mRxChIdx]); @@ -350,6 +363,7 @@ class HmRadio { uint8_t mTxChIdx; uint8_t mRxChIdx; + SPIClass* mSpi; RF24 mNrf24; uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE]; }; diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index 3f3b29a7..a95d4d24 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -21,9 +21,9 @@ class HmSystem { Radio.setup(); } - void setup(uint8_t ampPwr, uint8_t irqPin, uint8_t cePin, uint8_t csPin) { + void setup(uint8_t ampPwr, uint8_t irqPin, uint8_t cePin, uint8_t csPin, uint8_t sclkPin, uint8_t mosiPin, uint8_t misoPin) { mNumInv = 0; - Radio.setup(ampPwr, irqPin, cePin, csPin); + Radio.setup(ampPwr, irqPin, cePin, csPin, sclkPin, mosiPin, misoPin); } void addInverters(cfgInst_t *config) { diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 44f79e08..dbe43c06 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -448,8 +448,8 @@ const byteAssign_t InfoAssignment[] = { } else { bool change = false; if ( cmd >= 0x36 && cmd < 0x39 ) { // MI-1500 Data command - cmd++; // just request the next channel - change = true; + //cmd++; // just request the next channel + //change = true; } else if ( cmd == 0x09 ) {//MI single or dual channel device if ( mPayload[iv->id].dataAB[CH1] && iv->type == INV_TYPE_2CH ) { if (!mPayload[iv->id].stsAB[CH1] && mPayload[iv->id].retransmits<2) {} @@ -472,6 +472,7 @@ const byteAssign_t InfoAssignment[] = { if (change) { DBGPRINT(F("next request is")); //mPayload[iv->id].skipfirstrepeat = 0; + mPayload[iv->id].txCmd = cmd; } else { DBGPRINT(F("sth.")); DBGPRINT(F(" missing: Request Retransmit")); @@ -480,7 +481,6 @@ const byteAssign_t InfoAssignment[] = { DBGHEXLN(cmd); //mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd, true); mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, true, cmd); - mPayload[iv->id].txCmd = cmd; yield(); } } @@ -682,11 +682,13 @@ const byteAssign_t InfoAssignment[] = { }*/ miStsConsolidate(iv, datachan, rec, p->packet[23], p->packet[24]); - if (p->packet[0] < (0x39 + ALL_FRAMES) ) { /*uint8_t cmd = p->packet[0] - ALL_FRAMES + 1; mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); mPayload[iv->id].txCmd = cmd;*/ + mPayload[iv->id].txCmd++; + if (mPayload[iv->id].retransmits) + mPayload[iv->id].retransmits--; // reserve retransmissions for each response mPayload[iv->id].complete = false; } diff --git a/src/platformio.ini b/src/platformio.ini index 38e67c95..cae35934 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -37,7 +37,7 @@ lib_deps = https://github.com/yubox-node-org/ESPAsyncWebServer nrf24/RF24 @ ^1.4.5 paulstoffregen/Time @ ^1.6.1 - https://github.com/bertmelis/espMqttClient#v1.4.1 + https://github.com/bertmelis/espMqttClient#v1.4.2 bblanchon/ArduinoJson @ ^6.21.0 https://github.com/JChristensen/Timezone @ ^1.2.4 olikraus/U8g2 @ ^2.34.16 @@ -48,7 +48,8 @@ lib_deps = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = -D RELEASE -Wl,-Map,output.map +build_flags = -D RELEASE + ;-Wl,-Map,output.map monitor_filters = ;default ; Remove typical terminal control codes from input ;time ; Add timestamp with milliseconds for each new line @@ -133,3 +134,13 @@ monitor_filters = ;default ; Remove typical terminal control codes from input time ; Add timestamp with milliseconds for each new line log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory + +[env:opendtufusionv1-release] +platform = espressif32 +board = esp32-s3-devkitc-1 +build_flags = -D RELEASE -std=gnu++14 +build_unflags = -std=gnu++11 +monitor_filters = + ;default ; Remove typical terminal control codes from input + time ; Add timestamp with milliseconds for each new line + ;log2file ; Log data to a file “platformio-device-monitor-*.log” located in the current working directory diff --git a/src/plugins/Display/Display_ePaper.cpp b/src/plugins/Display/Display_ePaper.cpp index a2254b8d..99d35ed8 100644 --- a/src/plugins/Display/Display_ePaper.cpp +++ b/src/plugins/Display/Display_ePaper.cpp @@ -146,28 +146,28 @@ void DisplayEPaper::actualPowerPaged(float _totalPower, float _totalYieldDay, fl _display->setFont(&FreeSans12pt7b); y = _display->height() / 2; - _display->setCursor(0, y); + _display->setCursor(5, y); _display->print("today:"); snprintf(_fmtText, _display->width(), "%.0f", _totalYieldDay); _display->getTextBounds(_fmtText, 0, 0, &tbx, &tby, &tbw, &tbh); x = ((_display->width() - tbw) / 2) - tbx; _display->setCursor(x, y); _display->print(_fmtText); - _display->setCursor(_display->width() - 33, y); + _display->setCursor(_display->width() - 38, y); _display->println("Wh"); y = y + tbh + 7; - _display->setCursor(0, y); + _display->setCursor(5, y); _display->print("total:"); snprintf(_fmtText, _display->width(), "%.1f", _totalYieldTotal); _display->getTextBounds(_fmtText, 0, 0, &tbx, &tby, &tbw, &tbh); x = ((_display->width() - tbw) / 2) - tbx; _display->setCursor(x, y); _display->print(_fmtText); - _display->setCursor(_display->width() - 45, y); + _display->setCursor(_display->width() - 50, y); _display->println("kWh"); - _display->setCursor(0, _display->height() - (mHeadFootPadding + 10)); + _display->setCursor(10, _display->height() - (mHeadFootPadding + 10)); snprintf(_fmtText, sizeof(_fmtText), "%d Inverter online", _isprod); _display->println(_fmtText); diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index a529d1fc..b008d8d2 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -38,6 +38,7 @@ typedef struct { bool running; uint8_t lastIvId; uint8_t sub; + uint8_t foundIvCnt; } discovery_t; template @@ -100,7 +101,7 @@ class PubMqtt { if (mIntervalTimeout > 0) mIntervalTimeout--; - if(!mClient.connected()) { + if(mClient.disconnected()) { mClient.connect(); return; // next try in a second } @@ -117,9 +118,8 @@ class PubMqtt { } void tickerMinute() { - char val[12]; - snprintf(val, 12, "%ld", millis() / 1000); - publish(subtopics[MQTT_UPTIME], val); + snprintf(mVal, 40, "%ld", millis() / 1000); + publish(subtopics[MQTT_UPTIME], mVal); publish(subtopics[MQTT_RSSI], String(WiFi.RSSI()).c_str()); publish(subtopics[MQTT_FREE_HEAP], String(ESP.getFreeHeap()).c_str()); #ifndef ESP32 @@ -151,12 +151,10 @@ class PubMqtt { } void tickerMidnight() { - char topic[7 + MQTT_TOPIC_LEN], val[4]; - // set Total YieldDay to zero - snprintf(topic, 32 + MAX_NAME_LENGTH, "total/%s", fields[FLD_YD]); - snprintf(val, 2, "0"); - publish(topic, val, true); + snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[FLD_YD]); + snprintf(mVal, 2, "0"); + publish(mSubTopic, mVal, true); } void payloadEventListener(uint8_t cmd) { @@ -176,7 +174,6 @@ class PubMqtt { if(!mClient.connected()) return; - memset(mTopic, 0, MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1); if(addTopic){ snprintf(mTopic, MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1, "%s/%s", mCfgMqtt->topic, subTopic); } else { @@ -224,14 +221,13 @@ class PubMqtt { mDiscovery.running = true; mDiscovery.lastIvId = 0; mDiscovery.sub = 0; + mDiscovery.foundIvCnt = 0; } void setPowerLimitAck(Inverter<> *iv) { if (NULL != iv) { - char topic[7 + MQTT_TOPIC_LEN]; - - snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/%s", iv->config->name, subtopics[MQTT_ACK_PWR_LMT]); - publish(topic, "true", true); + snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/%s", iv->config->name, subtopics[MQTT_ACK_PWR_LMT]); + publish(mSubTopic, "true", true); } } @@ -245,12 +241,11 @@ class PubMqtt { tickerMinute(); publish(mLwtTopic, mqttStr[MQTT_STR_LWT_CONN], true, false); - char sub[20]; for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { - snprintf(sub, 20, "ctrl/limit/%d", i); - subscribe(sub); - snprintf(sub, 20, "ctrl/restart/%d", i); - subscribe(sub); + snprintf(mVal, 20, "ctrl/limit/%d", i); + subscribe(mVal); + snprintf(mVal, 20, "ctrl/restart/%d", i); + subscribe(mVal); } subscribe(subscr[MQTT_SUBS_SET_TIME]); } @@ -350,14 +345,16 @@ class PubMqtt { uint8_t fldTotal[4] = {FLD_PAC, FLD_YT, FLD_YD, FLD_PDC}; const char* unitTotal[4] = {"W", "kWh", "Wh", "W"}; - String node_mac = WiFi.macAddress().substring(12,14)+ WiFi.macAddress().substring(15,17); - String node_id = "AHOY_DTU_" + node_mac; + String node_id = String(mDevName) + "_TOTAL"; bool total = (mDiscovery.lastIvId == MAX_NUM_INVERTERS); Inverter<> *iv = mSys->getInverterByPos(mDiscovery.lastIvId); - record_t<> *rec; - if (NULL != iv) + record_t<> *rec = NULL; + if (NULL != iv) { rec = iv->getRecordStruct(RealTimeRunData_Debug); + if(0 == mDiscovery.sub) + mDiscovery.foundIvCnt++; + } if ((NULL != iv) || total) { if (!total) { @@ -412,7 +409,7 @@ class PubMqtt { if (!total) snprintf(topic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[mDiscovery.sub].ch, iv->getFieldName(mDiscovery.sub, rec)); else // total values - snprintf(topic, 64, "%s/sensor/%s/total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(),fields[fldTotal[mDiscovery.sub]]); + snprintf(topic, 64, "%s/sensor/%s/total_%s/config", MQTT_DISCOVERY_PREFIX, node_id.c_str(), fields[fldTotal[mDiscovery.sub]]); size_t size = measureJson(doc2) + 1; memset(buf, 0, size); serializeJson(doc2, buf, size); @@ -420,18 +417,25 @@ class PubMqtt { if(++mDiscovery.sub == ((!total) ? (rec->length) : 4)) { mDiscovery.sub = 0; - if(++mDiscovery.lastIvId == (MAX_NUM_INVERTERS + 1)) - mDiscovery.running = false; + checkDiscoveryEnd(); } } else { mDiscovery.sub = 0; - if(++mDiscovery.lastIvId == (MAX_NUM_INVERTERS + 1)) - mDiscovery.running = false; + checkDiscoveryEnd(); } yield(); } + void checkDiscoveryEnd(void) { + if(++mDiscovery.lastIvId == MAX_NUM_INVERTERS) { + // check if only one inverter was found, then don't create 'total' sensor + if(mDiscovery.foundIvCnt == 1) + mDiscovery.running = false; + } else if(mDiscovery.lastIvId == (MAX_NUM_INVERTERS + 1)) + mDiscovery.running = false; + } + const char *getFieldDeviceClass(uint8_t fieldId) { uint8_t pos = 0; for (; pos < DEVICE_CLS_ASSIGN_LIST_LEN; pos++) { @@ -455,7 +459,6 @@ class PubMqtt { bool allAvail = true; // shows if all enabled inverters are available bool anyAvail = false; // shows if at least one enabled inverter is available bool changed = false; - char topic[7 + MQTT_TOPIC_LEN], val[40]; Inverter<> *iv; record_t<> *rec; @@ -485,19 +488,19 @@ class PubMqtt { mLastIvState[id] = status; changed = true; - snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name); - snprintf(val, 40, "%d", status); - publish(topic, val, true); + snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name); + snprintf(mVal, 40, "%d", status); + publish(mSubTopic, mVal, true); - snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->name); - snprintf(val, 40, "%d", iv->getLastTs(rec)); - publish(topic, val, true); + snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->name); + snprintf(mVal, 40, "%d", iv->getLastTs(rec)); + publish(mSubTopic, mVal, true); } } if(changed) { - snprintf(val, 32, "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE))); - publish("status", val, true); + snprintf(mVal, 32, "%d", ((allAvail) ? MQTT_STATUS_ONLINE : ((anyAvail) ? MQTT_STATUS_PARTIAL : MQTT_STATUS_OFFLINE))); + publish("status", mVal, true); } return anyAvail; @@ -517,7 +520,6 @@ class PubMqtt { } void sendData(Inverter<> *iv, uint8_t curInfoCmd) { - char topic[7 + MQTT_TOPIC_LEN], val[40]; record_t<> *rec = iv->getRecordStruct(curInfoCmd); if (iv->getLastTs(rec) > 0) { @@ -534,9 +536,9 @@ class PubMqtt { } } - snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]); - snprintf(val, 40, "%g", ah::round3(iv->getValue(i, rec))); - publish(topic, val, retained); + snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]); + snprintf(mVal, 40, "%g", ah::round3(iv->getValue(i, rec))); + publish(mSubTopic, mVal, retained); yield(); } @@ -551,7 +553,6 @@ class PubMqtt { if(mSendList.empty()) return; - char topic[7 + MQTT_TOPIC_LEN], val[40]; float total[4]; bool RTRDataHasBeenSent = false; @@ -623,9 +624,9 @@ class PubMqtt { retained = false; break; } - snprintf(topic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); - snprintf(val, 40, "%g", ah::round3(total[i])); - publish(topic, val, retained); + snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]); + snprintf(mVal, 40, "%g", ah::round3(total[i])); + publish(mSubTopic, mVal, retained); } RTRDataHasBeenSent = true; yield(); @@ -658,9 +659,10 @@ class PubMqtt { char mLwtTopic[MQTT_TOPIC_LEN+5]; const char *mDevName, *mVersion; char mClientId[24]; // number of chars is limited to 23 up to v3.1 of MQTT - // global buffer for mqtt topic. Used when publishing mqtt messages. + // global buffer for mqtt topic. Used when publishing mqtt messages. char mTopic[MQTT_TOPIC_LEN + 32 + MAX_NAME_LENGTH + 1]; - + char mSubTopic[32 + MAX_NAME_LENGTH + 1]; + char mVal[40]; discovery_t mDiscovery; }; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 15402e7a..b224f239 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -386,6 +386,9 @@ class RestApi { obj[F("cs")] = mConfig->nrf.pinCs; obj[F("ce")] = mConfig->nrf.pinCe; obj[F("irq")] = mConfig->nrf.pinIrq; + obj[F("sclk")] = mConfig->nrf.pinSclk; + obj[F("mosi")] = mConfig->nrf.pinMosi; + obj[F("miso")] = mConfig->nrf.pinMiso; obj[F("led0")] = mConfig->led.led0; obj[F("led1")] = mConfig->led.led1; } diff --git a/src/web/html/about.html b/src/web/html/about.html new file mode 100644 index 00000000..c0eb8c5e --- /dev/null +++ b/src/web/html/about.html @@ -0,0 +1,57 @@ + + + + About + {#HTML_HEADER} + + + {#HTML_NAV} +
+
+

About AhoyDTU

+
+
+
Used Libraries
+
+ + + + + + + + +
+
Contact Information
+
+
+
Github Repository
+ +
+
+
Discord Chat
+ +
+
+
E-Mail
+ +
+
+
+
+ {#HTML_FOOTER} + + + diff --git a/src/web/html/api.js b/src/web/html/api.js index 6e63740d..5ccb0e15 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -74,7 +74,7 @@ function topnav() { } function parseNav(obj) { - for(i = 0; i < 10; i++) { + for(i = 0; i < 11; i++) { if(i == 2) continue; var l = document.getElementById("nav"+i); diff --git a/src/web/html/includes/nav.html b/src/web/html/includes/nav.html index f1e1a2bd..3dac1590 100644 --- a/src/web/html/includes/nav.html +++ b/src/web/html/includes/nav.html @@ -15,11 +15,10 @@ REST API Documentation + About Login Logout
- - diff --git a/src/web/html/setup.html b/src/web/html/setup.html index a335f76f..bfbda402 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -363,6 +363,54 @@ [36, "VP (GPIO36)"], [39, "VN (GPIO39)"] ]; + var esp32s3pins = [ + [255, "off / default"], + [0, "GPIO0 (DONT USE - BOOT)"], + [1, "GPIO1"], + [2, "GPIO2"], + [3, "GPIO3"], + [4, "GPIO4"], + [5, "GPIO5"], + [6, "GPIO6"], + [7, "GPIO7"], + [8, "GPIO8"], + [9, "GPIO9"], + [10, "GPIO10"], + [11, "GPIO11"], + [12, "GPIO12"], + [13, "GPIO13"], + [14, "GPIO14"], + [15, "GPIO15"], + [16, "GPIO16"], + [17, "GPIO17"], + [18, "GPIO18"], + [19, "GPIO19 (DONT USE - USB-)"], + [20, "GPIO20 (DONT USE - USB+)"], + [21, "GPIO21"], + [26, "GPIO26 (PSRAM - not available)"], + [27, "GPIO27 (FLASH - not available)"], + [28, "GPIO28 (FLASH - not available)"], + [29, "GPIO29 (FLASH - not available)"], + [30, "GPIO30 (FLASH - not available)"], + [31, "GPIO31 (FLASH - not available)"], + [32, "GPIO32 (FLASH - not available)"], + [33, "GPIO33 (not exposed on WROOM modules)"], + [34, "GPIO34 (not exposed on WROOM modules)"], + [35, "GPIO35"], + [36, "GPIO36"], + [37, "GPIO37"], + [38, "GPIO38"], + [39, "GPIO39"], + [40, "GPIO40"], + [41, "GPIO41"], + [42, "GPIO42"], + [43, "GPIO43"], + [44, "GPIO44"], + [45, "GPIO45 (DONT USE - STRAPPING PIN)"], + [46, "GPIO46 (DONT USE - STRAPPING PIN)"], + [47, "GPIO47"], + [48, "GPIO48"], + ]; const re = /11[2,4,6]1.*/; @@ -605,15 +653,19 @@ } } - function parsePinout(obj, type) { + function parsePinout(obj, type, system) { var e = document.getElementById("pinout"); - pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['led0', 'pinLed0'], ['led1', 'pinLed1']]; + if ("ESP8266" == type) { + pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['led0', 'pinLed0'], ['led1', 'pinLed1']]; + } else { + pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['sclk', 'pinSclk'], ['mosi', 'pinMosi'], ['miso', 'pinMiso'], ['led0', 'pinLed0'], ['led1', 'pinLed1']]; + } for(p of pins) { e.append( ml("div", {class: "row mb-3"}, [ ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), ml("div", {class: "col-12 col-sm-9"}, - sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[0]]) + sel(p[1], ("ESP8266" == type) ? esp8266pins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, obj[p[0]]) ) ]) ); @@ -642,7 +694,7 @@ document.getElementsByName("serIntvl")[0].value = obj["interval"]; } - function parseDisplay(obj, type) { + function parseDisplay(obj, type, system) { for(var i of ["disp_pwr", "disp_pxshift"]) document.getElementsByName(i)[0].checked = obj[i]; @@ -655,7 +707,7 @@ ml("div", {class: "row mb-3", id: "row_" + p[1]}, [ ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), ml("div", {class: "col-12 col-sm-9"}, - sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[1]]) + sel(p[1], ("ESP8266" == type) ? esp8266pins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, obj[p[1]]) ) ]) ); @@ -720,10 +772,10 @@ parseMqtt(root["mqtt"]); parseNtp(root["ntp"]); parseSun(root["sun"]); - parsePinout(root["pinout"], root["system"]["esp_type"]); + parsePinout(root["pinout"], root["system"]["esp_type"], root["system"]); parseRadio(root["radio"]); parseSerial(root["serial"]); - parseDisplay(root["display"], root["system"]["esp_type"]); + parseDisplay(root["display"], root["system"]["esp_type"], root["system"]); getAjax("/api/inverter/list", parseIv); } } diff --git a/src/web/web.h b/src/web/web.h index eca78f87..47bdeb1d 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -30,10 +30,11 @@ #include "html/h/save_html.h" #include "html/h/update_html.h" #include "html/h/visualization_html.h" +#include "html/h/about_html.h" #define WEB_SERIAL_BUF_SIZE 2048 -const char *const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinLed0", "pinLed1"}; +const char *const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinSclk", "pinMosi", "pinMiso", "pinLed0", "pinLed1"}; template class Web { @@ -83,6 +84,7 @@ class Web { mWeb.on("/upload", HTTP_POST, std::bind(&Web::onUpload, this, std::placeholders::_1), std::bind(&Web::onUpload2, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6)); mWeb.on("/serial", HTTP_GET, std::bind(&Web::onSerial, this, std::placeholders::_1)); + mWeb.on("/about", HTTP_GET, std::bind(&Web::onAbout, this, std::placeholders::_1)); mWeb.on("/debug", HTTP_GET, std::bind(&Web::onDebug, this, std::placeholders::_1)); @@ -141,16 +143,14 @@ class Web { } } if (!Update.hasError()) { - if (Update.write(data, len) != len) { + if (Update.write(data, len) != len) Update.printError(Serial); - } } if (final) { - if (Update.end(true)) { + if (Update.end(true)) Serial.printf("Update Success: %uB\n", index + len); - } else { + else Update.printError(Serial); - } } } @@ -245,7 +245,7 @@ class Web { } void showUpdate(AsyncWebServerRequest *request) { - bool reboot = !Update.hasError(); + bool reboot = (!Update.hasError()); String html = F("UpdateUpdate: "); if (reboot) @@ -521,14 +521,17 @@ class Web { // pinout uint8_t pin; - for (uint8_t i = 0; i < 5; i++) { + for (uint8_t i = 0; i < 8; i++) { pin = request->arg(String(pinArgNames[i])).toInt(); switch(i) { default: mConfig->nrf.pinCs = ((pin != 0xff) ? pin : DEF_CS_PIN); break; case 1: mConfig->nrf.pinCe = ((pin != 0xff) ? pin : DEF_CE_PIN); break; case 2: mConfig->nrf.pinIrq = ((pin != 0xff) ? pin : DEF_IRQ_PIN); break; - case 3: mConfig->led.led0 = pin; break; - case 4: mConfig->led.led1 = pin; break; + case 3: mConfig->nrf.pinSclk = ((pin != 0xff) ? pin : DEF_SCLK_PIN); break; + case 4: mConfig->nrf.pinMosi = ((pin != 0xff) ? pin : DEF_MOSI_PIN); break; + case 5: mConfig->nrf.pinMiso = ((pin != 0xff) ? pin : DEF_MISO_PIN); break; + case 6: mConfig->led.led0 = pin; break; + case 7: mConfig->led.led1 = pin; break; } } @@ -615,6 +618,21 @@ class Web { request->send(response); } + void onAbout(AsyncWebServerRequest *request) { + if (CHECK_MASK(mConfig->sys.protectionMask, PROT_MASK_LIVE)) { + if (mProtected) { + checkRedirect(request); + return; + } + } + + AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), about_html, about_html_len); + response->addHeader(F("Content-Encoding"), "gzip"); + response->addHeader(F("content-type"), "text/html; charset=UTF-8"); + + request->send(response); + } + void onDebug(AsyncWebServerRequest *request) { mApp->getSchedulerNames(); AsyncWebServerResponse *response = request->beginResponse(200, F("text/html; charset=UTF-8"), "ok");