diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4fa430ea..d557ccc6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,7 +37,7 @@ jobs: - name: Get default environments id: envs run: | - echo "environments=$(pio project config --json-output | jq -cr '.[0][1][0][1]')" >> $GITHUB_OUTPUT + echo "environments=$(pio project config --json-output | jq -cr '.[1][1][0][1]|split(",")')" >> $GITHUB_OUTPUT outputs: environments: ${{ steps.envs.outputs.environments }} @@ -98,17 +98,15 @@ jobs: - name: Rename Firmware run: mv .pio/build/${{ matrix.environment }}/firmware.bin .pio/build/${{ matrix.environment }}/opendtu-${{ matrix.environment }}.bin - - name: Copy boot_app0.bin - run: cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin .pio/build/${{ matrix.environment }}/boot_app0.bin + - name: Rename Factory Firmware + run: mv .pio/build/${{ matrix.environment }}/firmware.factory.bin .pio/build/${{ matrix.environment }}/opendtu-${{ matrix.environment }}.factory.bin - uses: actions/upload-artifact@v3 with: name: opendtu-${{ matrix.environment }} path: | .pio/build/${{ matrix.environment }}/opendtu-${{ matrix.environment }}.bin - .pio/build/${{ matrix.environment }}/partitions.bin - .pio/build/${{ matrix.environment }}/bootloader.bin - .pio/build/${{ matrix.environment }}/boot_app0.bin + .pio/build/${{ matrix.environment }}/opendtu-${{ matrix.environment }}.factory.bin release: name: Create Release @@ -121,7 +119,7 @@ jobs: - name: Build Changelog id: github_release - uses: mikepenz/release-changelog-builder-action@v3.7.0 + uses: mikepenz/release-changelog-builder-action@v3 with: failOnError: true commitMode: true @@ -133,12 +131,10 @@ jobs: with: path: artifacts/ - - name: Create ZIPs + - name: Move all files to the same location run: | ls -R - sudo apt install zip cd artifacts - for i in */; do zip -r "${i%/}.zip" "$i"; done for i in */; do cp ${i}opendtu-*.bin ./; done - name: Create release diff --git a/README.md b/README.md index 5dbc8a24..005fd28f 100644 --- a/README.md +++ b/README.md @@ -210,14 +210,7 @@ It is recommended to make all changes only in the 'platformio_override.ini', th ### using the pre-compiled .bin files -The pre-compiled binary files can be found here on the [github page behind "Releases"](https://github.com/tbnobody/OpenDTU/releases) (look at the right column). For a first installation on an ESP32, download `opendtu-generic.zip`, unpack and use a ESP32 flash tool of your choice (see next chapter) to flash the `.bin` files to the right addresses: - -| Address | File | -| ---------| ---------------------- | -| 0x1000 | bootloader.bin | -| 0x8000 | partitions.bin | -| 0xe000 | boot_app0.bin | -| 0x10000 | opendtu-*.bin | +The pre-compiled binary files can be found here on the [github page behind "Releases"](https://github.com/tbnobody/OpenDTU/releases) (look at the right column). For a first installation on an ESP32, download `opendtu-generic.factory.bin` and use a ESP32 flash tool of your choice to flash the `.bin` file to the address `0x0`. (The previous method with different .bin files is no more necessary.) For further updates download `opendtu-generic.bin` and use the over-the-air firmware update in OpenDTU's web interface. @@ -226,10 +219,7 @@ For further updates download `opendtu-generic.bin` and use the over-the-air firm ```bash esptool.py --port /dev/ttyUSB0 --chip esp32 --before default_reset --after hard_reset \ write_flash --flash_mode dout --flash_freq 40m --flash_size detect \ - 0x1000 bootloader.bin \ - 0x8000 partitions.bin \ - 0xe000 boot_app0.bin \ - 0x10000 opendtu-generic.bin + 0x0 opendtu-generic.factory.bin ``` #### Flash with Espressif Flash Download Tool (Windows) diff --git a/docs/DeviceProfiles/nodemcu_esp32.json b/docs/DeviceProfiles/nodemcu_esp32.json index a42af371..d7f6a614 100644 --- a/docs/DeviceProfiles/nodemcu_esp32.json +++ b/docs/DeviceProfiles/nodemcu_esp32.json @@ -1,6 +1,6 @@ [ { - "name": "Generic NodeMCU 32", + "name": "NRF24", "nrf24": { "miso": 19, "mosi": 23, @@ -10,17 +10,11 @@ "cs": 5 }, "eth": { - "enabled": false, - "phy_addr": -1, - "power": -1, - "mdc": -1, - "mdio": -1, - "type": 0, - "clk_mode": 0 + "enabled": false } }, { - "name": "Generic NodeMCU 32 with CMT2300A", + "name": "CMT2300A", "nrf24": { "miso": -1, "mosi": -1, @@ -38,17 +32,11 @@ "gpio3": 16 }, "eth": { - "enabled": false, - "phy_addr": -1, - "power": -1, - "mdc": -1, - "mdio": -1, - "type": 0, - "clk_mode": 0 + "enabled": false } }, { - "name": "Generic NodeMCU 32 with SSD1306", + "name": "NRF24 with SSD1306", "nrf24": { "miso": 19, "mosi": 23, @@ -58,13 +46,7 @@ "cs": 5 }, "eth": { - "enabled": false, - "phy_addr": -1, - "power": -1, - "mdc": -1, - "mdio": -1, - "type": 0, - "clk_mode": 0 + "enabled": false }, "display": { "type": 2, @@ -73,7 +55,7 @@ } }, { - "name": "Generic NodeMCU 32 with SH1106", + "name": "NRF24 with SH1106", "nrf24": { "miso": 19, "mosi": 23, @@ -83,13 +65,7 @@ "cs": 5 }, "eth": { - "enabled": false, - "phy_addr": -1, - "power": -1, - "mdc": -1, - "mdio": -1, - "type": 0, - "clk_mode": 0 + "enabled": false }, "display": { "type": 3, @@ -98,7 +74,61 @@ } }, { - "name": "Generic NodeMCU 32 with NRF + CMT Module", + "name": "CMT2300A with SSD1306", + "nrf24": { + "miso": -1, + "mosi": -1, + "clk": -1, + "irq": -1, + "en": -1, + "cs": -1 + }, + "cmt": { + "clk": 18, + "cs": 4, + "fcs": 5, + "sdio": 23, + "gpio2": 19, + "gpio3": 16 + }, + "eth": { + "enabled": false + }, + "display": { + "type": 2, + "data": 21, + "clk": 22 + } + }, + { + "name": "CMT2300A with SH1106", + "nrf24": { + "miso": -1, + "mosi": -1, + "clk": -1, + "irq": -1, + "en": -1, + "cs": -1 + }, + "cmt": { + "clk": 18, + "cs": 4, + "fcs": 5, + "sdio": 23, + "gpio2": 19, + "gpio3": 16 + }, + "eth": { + "enabled": false + }, + "display": { + "type": 3, + "data": 21, + "clk": 22 + } + }, + { + "name": "NRF24 + CMT2300A", "nrf24": { "miso": 19, "mosi": 23, diff --git a/docs/esp32_flash_download_tool.png b/docs/esp32_flash_download_tool.png index 3f970e63..7114d4c9 100644 Binary files a/docs/esp32_flash_download_tool.png and b/docs/esp32_flash_download_tool.png differ diff --git a/lib/Hoymiles/src/HoymilesRadio.cpp b/lib/Hoymiles/src/HoymilesRadio.cpp index 8faf1727..fc1ca409 100644 --- a/lib/Hoymiles/src/HoymilesRadio.cpp +++ b/lib/Hoymiles/src/HoymilesRadio.cpp @@ -51,6 +51,69 @@ void HoymilesRadio::sendLastPacketAgain() sendEsbPacket(cmd); } +void HoymilesRadio::handleReceivedPackage() +{ + if (_busyFlag && _rxTimeout.occured()) { + Hoymiles.getMessageOutput()->println("RX Period End"); + std::shared_ptr inv = Hoymiles.getInverterBySerial(_commandQueue.front().get()->getTargetAddress()); + + if (nullptr != inv) { + CommandAbstract* cmd = _commandQueue.front().get(); + uint8_t verifyResult = inv->verifyAllFragments(cmd); + if (verifyResult == FRAGMENT_ALL_MISSING_RESEND) { + Hoymiles.getMessageOutput()->println("Nothing received, resend whole request"); + sendLastPacketAgain(); + + } else if (verifyResult == FRAGMENT_ALL_MISSING_TIMEOUT) { + Hoymiles.getMessageOutput()->println("Nothing received, resend count exeeded"); + _commandQueue.pop(); + _busyFlag = false; + + } else if (verifyResult == FRAGMENT_RETRANSMIT_TIMEOUT) { + Hoymiles.getMessageOutput()->println("Retransmit timeout"); + _commandQueue.pop(); + _busyFlag = false; + + } else if (verifyResult == FRAGMENT_HANDLE_ERROR) { + Hoymiles.getMessageOutput()->println("Packet handling error"); + _commandQueue.pop(); + _busyFlag = false; + + } else if (verifyResult > 0) { + // Perform Retransmit + Hoymiles.getMessageOutput()->print("Request retransmit: "); + Hoymiles.getMessageOutput()->println(verifyResult); + sendRetransmitPacket(verifyResult); + + } else { + // Successful received all packages + Hoymiles.getMessageOutput()->println("Success"); + _commandQueue.pop(); + _busyFlag = false; + } + } else { + // If inverter was not found, assume the command is invalid + Hoymiles.getMessageOutput()->println("RX: Invalid inverter found"); + _commandQueue.pop(); + _busyFlag = false; + } + } else if (!_busyFlag) { + // Currently in idle mode --> send packet if one is in the queue + if (!_commandQueue.empty()) { + CommandAbstract* cmd = _commandQueue.front().get(); + + auto inv = Hoymiles.getInverterBySerial(cmd->getTargetAddress()); + if (nullptr != inv) { + inv->clearRxFragmentBuffer(); + sendEsbPacket(cmd); + } else { + Hoymiles.getMessageOutput()->println("TX: Invalid inverter found"); + _commandQueue.pop(); + } + } + } +} + void HoymilesRadio::dumpBuf(const uint8_t buf[], uint8_t len, bool appendNewline) { for (uint8_t i = 0; i < len; i++) { diff --git a/lib/Hoymiles/src/HoymilesRadio.h b/lib/Hoymiles/src/HoymilesRadio.h index 2ee2ad25..21477293 100644 --- a/lib/Hoymiles/src/HoymilesRadio.h +++ b/lib/Hoymiles/src/HoymilesRadio.h @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once +#include "TimeoutHelper.h" #include "commands/CommandAbstract.h" #include "types.h" #include @@ -30,9 +31,12 @@ protected: virtual void sendEsbPacket(CommandAbstract* cmd) = 0; void sendRetransmitPacket(uint8_t fragment_id); void sendLastPacketAgain(); + void handleReceivedPackage(); serial_u _dtuSerial; std::queue> _commandQueue; bool _isInitialized = false; bool _busyFlag = false; + + TimeoutHelper _rxTimeout; }; \ No newline at end of file diff --git a/lib/Hoymiles/src/HoymilesRadio_CMT.cpp b/lib/Hoymiles/src/HoymilesRadio_CMT.cpp index 4c3285f5..b2044649 100644 --- a/lib/Hoymiles/src/HoymilesRadio_CMT.cpp +++ b/lib/Hoymiles/src/HoymilesRadio_CMT.cpp @@ -151,65 +151,7 @@ void HoymilesRadio_CMT::loop() } } - if (_busyFlag && _rxTimeout.occured()) { - Hoymiles.getMessageOutput()->println("RX Period End"); - std::shared_ptr inv = Hoymiles.getInverterBySerial(_commandQueue.front().get()->getTargetAddress()); - - if (nullptr != inv) { - CommandAbstract* cmd = _commandQueue.front().get(); - uint8_t verifyResult = inv->verifyAllFragments(cmd); - if (verifyResult == FRAGMENT_ALL_MISSING_RESEND) { - Hoymiles.getMessageOutput()->println("Nothing received, resend whole request"); - sendLastPacketAgain(); - - } else if (verifyResult == FRAGMENT_ALL_MISSING_TIMEOUT) { - Hoymiles.getMessageOutput()->println("Nothing received, resend count exeeded"); - _commandQueue.pop(); - _busyFlag = false; - - } else if (verifyResult == FRAGMENT_RETRANSMIT_TIMEOUT) { - Hoymiles.getMessageOutput()->println("Retransmit timeout"); - _commandQueue.pop(); - _busyFlag = false; - - } else if (verifyResult == FRAGMENT_HANDLE_ERROR) { - Hoymiles.getMessageOutput()->println("Packet handling error"); - _commandQueue.pop(); - _busyFlag = false; - - } else if (verifyResult > 0) { - // Perform Retransmit - Hoymiles.getMessageOutput()->print("Request retransmit: "); - Hoymiles.getMessageOutput()->println(verifyResult); - sendRetransmitPacket(verifyResult); - - } else { - // Successful received all packages - Hoymiles.getMessageOutput()->println("Success"); - _commandQueue.pop(); - _busyFlag = false; - } - } else { - // If inverter was not found, assume the command is invalid - Hoymiles.getMessageOutput()->println("RX: Invalid inverter found"); - _commandQueue.pop(); - _busyFlag = false; - } - } else if (!_busyFlag) { - // Currently in idle mode --> send packet if one is in the queue - if (!_commandQueue.empty()) { - CommandAbstract* cmd = _commandQueue.front().get(); - - auto inv = Hoymiles.getInverterBySerial(cmd->getTargetAddress()); - if (nullptr != inv) { - inv->clearRxFragmentBuffer(); - sendEsbPacket(cmd); - } else { - Hoymiles.getMessageOutput()->println("TX: Invalid inverter found"); - _commandQueue.pop(); - } - } - } + handleReceivedPackage(); } void HoymilesRadio_CMT::setPALevel(int8_t paLevel) diff --git a/lib/Hoymiles/src/HoymilesRadio_CMT.h b/lib/Hoymiles/src/HoymilesRadio_CMT.h index b1cfa7c4..66314b3d 100644 --- a/lib/Hoymiles/src/HoymilesRadio_CMT.h +++ b/lib/Hoymiles/src/HoymilesRadio_CMT.h @@ -2,7 +2,6 @@ #pragma once #include "HoymilesRadio.h" -#include "TimeoutHelper.h" #include "commands/CommandAbstract.h" #include "types.h" #include @@ -48,7 +47,6 @@ private: bool _gpio3_configured = false; std::queue _rxBuffer; - TimeoutHelper _rxTimeout; TimeoutHelper _txTimeout; uint32_t _inverterTargetFrequency = HOYMILES_CMT_WORK_FREQ; diff --git a/lib/Hoymiles/src/HoymilesRadio_NRF.cpp b/lib/Hoymiles/src/HoymilesRadio_NRF.cpp index 88b7dbb6..ecb9501e 100644 --- a/lib/Hoymiles/src/HoymilesRadio_NRF.cpp +++ b/lib/Hoymiles/src/HoymilesRadio_NRF.cpp @@ -55,6 +55,7 @@ void HoymilesRadio_NRF::loop() memset(f.fragment, 0xcc, MAX_RF_PAYLOAD_SIZE); f.len = _radio->getDynamicPayloadSize(); f.channel = _radio->getChannel(); + f.rssi = _radio->testRPD() ? -30 : -80; if (f.len > MAX_RF_PAYLOAD_SIZE) f.len = MAX_RF_PAYLOAD_SIZE; _radio->read(f.fragment, f.len); @@ -76,7 +77,9 @@ void HoymilesRadio_NRF::loop() if (nullptr != inv) { // Save packet in inverter rx buffer Hoymiles.getMessageOutput()->printf("RX Channel: %d --> ", f.channel); - dumpBuf(f.fragment, f.len); + dumpBuf(f.fragment, f.len, false); + Hoymiles.getMessageOutput()->printf("| %d dBm\r\n", f.rssi); + inv->addRxFragment(f.fragment, f.len); } else { Hoymiles.getMessageOutput()->println("Inverter Not found!"); @@ -91,65 +94,7 @@ void HoymilesRadio_NRF::loop() } } - if (_busyFlag && _rxTimeout.occured()) { - Hoymiles.getMessageOutput()->println("RX Period End"); - std::shared_ptr inv = Hoymiles.getInverterBySerial(_commandQueue.front().get()->getTargetAddress()); - - if (nullptr != inv) { - CommandAbstract* cmd = _commandQueue.front().get(); - uint8_t verifyResult = inv->verifyAllFragments(cmd); - if (verifyResult == FRAGMENT_ALL_MISSING_RESEND) { - Hoymiles.getMessageOutput()->println("Nothing received, resend whole request"); - sendLastPacketAgain(); - - } else if (verifyResult == FRAGMENT_ALL_MISSING_TIMEOUT) { - Hoymiles.getMessageOutput()->println("Nothing received, resend count exeeded"); - _commandQueue.pop(); - _busyFlag = false; - - } else if (verifyResult == FRAGMENT_RETRANSMIT_TIMEOUT) { - Hoymiles.getMessageOutput()->println("Retransmit timeout"); - _commandQueue.pop(); - _busyFlag = false; - - } else if (verifyResult == FRAGMENT_HANDLE_ERROR) { - Hoymiles.getMessageOutput()->println("Packet handling error"); - _commandQueue.pop(); - _busyFlag = false; - - } else if (verifyResult > 0) { - // Perform Retransmit - Hoymiles.getMessageOutput()->print("Request retransmit: "); - Hoymiles.getMessageOutput()->println(verifyResult); - sendRetransmitPacket(verifyResult); - - } else { - // Successful received all packages - Hoymiles.getMessageOutput()->println("Success"); - _commandQueue.pop(); - _busyFlag = false; - } - } else { - // If inverter was not found, assume the command is invalid - Hoymiles.getMessageOutput()->println("RX: Invalid inverter found"); - _commandQueue.pop(); - _busyFlag = false; - } - } else if (!_busyFlag) { - // Currently in idle mode --> send packet if one is in the queue - if (!_commandQueue.empty()) { - CommandAbstract* cmd = _commandQueue.front().get(); - - auto inv = Hoymiles.getInverterBySerial(cmd->getTargetAddress()); - if (nullptr != inv) { - inv->clearRxFragmentBuffer(); - sendEsbPacket(cmd); - } else { - Hoymiles.getMessageOutput()->println("TX: Invalid inverter found"); - _commandQueue.pop(); - } - } - } + handleReceivedPackage(); } void HoymilesRadio_NRF::setPALevel(rf24_pa_dbm_e paLevel) diff --git a/lib/Hoymiles/src/HoymilesRadio_NRF.h b/lib/Hoymiles/src/HoymilesRadio_NRF.h index 88c0d2f9..8530a0e3 100644 --- a/lib/Hoymiles/src/HoymilesRadio_NRF.h +++ b/lib/Hoymiles/src/HoymilesRadio_NRF.h @@ -2,7 +2,6 @@ #pragma once #include "HoymilesRadio.h" -#include "TimeoutHelper.h" #include "commands/CommandAbstract.h" #include #include @@ -44,5 +43,4 @@ private: volatile bool _packetReceived = false; std::queue _rxBuffer; - TimeoutHelper _rxTimeout; }; \ No newline at end of file diff --git a/lib/Hoymiles/src/inverters/HMT_6CH.cpp b/lib/Hoymiles/src/inverters/HMT_6CH.cpp index eea3353d..e54382ea 100644 --- a/lib/Hoymiles/src/inverters/HMT_6CH.cpp +++ b/lib/Hoymiles/src/inverters/HMT_6CH.cpp @@ -5,47 +5,47 @@ #include "HMT_6CH.h" static const byteAssign_t byteAssignment[] = { - { TYPE_DC, CH0, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 }, - { TYPE_DC, CH0, FLD_IDC, UNIT_A, 4, 2, 100, false, 2 }, - { TYPE_DC, CH0, FLD_PDC, UNIT_W, 8, 2, 10, false, 1 }, - { TYPE_DC, CH0, FLD_YT, UNIT_KWH, 12, 4, 1000, false, 3 }, - { TYPE_DC, CH0, FLD_YD, UNIT_WH, 20, 2, 1, false, 0 }, - { TYPE_DC, CH0, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH0, CMD_CALC, false, 3 }, + { TYPE_DC, CH0, FLD_UDC, UNIT_V, 46, 2, 10, false, 1 }, + { TYPE_DC, CH0, FLD_IDC, UNIT_A, 50, 2, 100, false, 2 }, + { TYPE_DC, CH0, FLD_PDC, UNIT_W, 54, 2, 10, false, 1 }, + { TYPE_DC, CH0, FLD_YT, UNIT_KWH, 60, 4, 1000, false, 3 }, + { TYPE_DC, CH0, FLD_YD, UNIT_WH, 66, 2, 1, false, 0 }, + { TYPE_DC, CH0, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH5, CMD_CALC, false, 3 }, - { TYPE_DC, CH1, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 }, - { TYPE_DC, CH1, FLD_IDC, UNIT_A, 6, 2, 100, false, 2 }, - { TYPE_DC, CH1, FLD_PDC, UNIT_W, 10, 2, 10, false, 1 }, - { TYPE_DC, CH1, FLD_YT, UNIT_KWH, 16, 4, 1000, false, 3 }, - { TYPE_DC, CH1, FLD_YD, UNIT_WH, 22, 2, 1, false, 0 }, - { TYPE_DC, CH1, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH1, CMD_CALC, false, 3 }, + { TYPE_DC, CH1, FLD_UDC, UNIT_V, 46, 2, 10, false, 1 }, + { TYPE_DC, CH1, FLD_IDC, UNIT_A, 48, 2, 100, false, 2 }, + { TYPE_DC, CH1, FLD_PDC, UNIT_W, 52, 2, 10, false, 1 }, + { TYPE_DC, CH1, FLD_YT, UNIT_KWH, 56, 4, 1000, false, 3 }, + { TYPE_DC, CH1, FLD_YD, UNIT_WH, 64, 2, 1, false, 0 }, + { TYPE_DC, CH1, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH4, CMD_CALC, false, 3 }, { TYPE_DC, CH2, FLD_UDC, UNIT_V, 24, 2, 10, false, 1 }, - { TYPE_DC, CH2, FLD_IDC, UNIT_A, 26, 2, 100, false, 2 }, - { TYPE_DC, CH2, FLD_PDC, UNIT_W, 30, 2, 10, false, 1 }, - { TYPE_DC, CH2, FLD_YT, UNIT_KWH, 34, 4, 1000, false, 3 }, - { TYPE_DC, CH2, FLD_YD, UNIT_WH, 42, 2, 1, false, 0 }, - { TYPE_DC, CH2, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH2, CMD_CALC, false, 3 }, + { TYPE_DC, CH2, FLD_IDC, UNIT_A, 28, 2, 100, false, 2 }, + { TYPE_DC, CH2, FLD_PDC, UNIT_W, 32, 2, 10, false, 1 }, + { TYPE_DC, CH2, FLD_YT, UNIT_KWH, 38, 4, 1000, false, 3 }, + { TYPE_DC, CH2, FLD_YD, UNIT_WH, 44, 2, 1, false, 0 }, + { TYPE_DC, CH2, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH3, CMD_CALC, false, 3 }, { TYPE_DC, CH3, FLD_UDC, UNIT_V, 24, 2, 10, false, 1 }, - { TYPE_DC, CH3, FLD_IDC, UNIT_A, 28, 2, 100, false, 2 }, - { TYPE_DC, CH3, FLD_PDC, UNIT_W, 32, 2, 10, false, 1 }, - { TYPE_DC, CH3, FLD_YT, UNIT_KWH, 38, 4, 1000, false, 3 }, - { TYPE_DC, CH3, FLD_YD, UNIT_WH, 44, 2, 1, false, 0 }, - { TYPE_DC, CH3, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH3, CMD_CALC, false, 3 }, + { TYPE_DC, CH3, FLD_IDC, UNIT_A, 26, 2, 100, false, 2 }, + { TYPE_DC, CH3, FLD_PDC, UNIT_W, 30, 2, 10, false, 1 }, + { TYPE_DC, CH3, FLD_YT, UNIT_KWH, 34, 4, 1000, false, 3 }, + { TYPE_DC, CH3, FLD_YD, UNIT_WH, 42, 2, 1, false, 0 }, + { TYPE_DC, CH3, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH2, CMD_CALC, false, 3 }, - { TYPE_DC, CH4, FLD_UDC, UNIT_V, 46, 2, 10, false, 1 }, - { TYPE_DC, CH4, FLD_IDC, UNIT_A, 48, 2, 100, false, 2 }, - { TYPE_DC, CH4, FLD_PDC, UNIT_W, 52, 2, 10, false, 1 }, - { TYPE_DC, CH4, FLD_YT, UNIT_KWH, 56, 4, 1000, false, 3 }, - { TYPE_DC, CH4, FLD_YD, UNIT_WH, 64, 2, 1, false, 0 }, - { TYPE_DC, CH4, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH4, CMD_CALC, false, 3 }, + { TYPE_DC, CH4, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 }, + { TYPE_DC, CH4, FLD_IDC, UNIT_A, 6, 2, 100, false, 2 }, + { TYPE_DC, CH4, FLD_PDC, UNIT_W, 10, 2, 10, false, 1 }, + { TYPE_DC, CH4, FLD_YT, UNIT_KWH, 16, 4, 1000, false, 3 }, + { TYPE_DC, CH4, FLD_YD, UNIT_WH, 22, 2, 1, false, 0 }, + { TYPE_DC, CH4, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH1, CMD_CALC, false, 3 }, - { TYPE_DC, CH5, FLD_UDC, UNIT_V, 46, 2, 10, false, 1 }, - { TYPE_DC, CH5, FLD_IDC, UNIT_A, 50, 2, 100, false, 2 }, - { TYPE_DC, CH5, FLD_PDC, UNIT_W, 54, 2, 10, false, 1 }, - { TYPE_DC, CH5, FLD_YT, UNIT_KWH, 60, 4, 1000, false, 3 }, - { TYPE_DC, CH5, FLD_YD, UNIT_WH, 66, 2, 1, false, 0 }, - { TYPE_DC, CH5, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH5, CMD_CALC, false, 3 }, + { TYPE_DC, CH5, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 }, + { TYPE_DC, CH5, FLD_IDC, UNIT_A, 4, 2, 100, false, 2 }, + { TYPE_DC, CH5, FLD_PDC, UNIT_W, 8, 2, 10, false, 1 }, + { TYPE_DC, CH5, FLD_YT, UNIT_KWH, 12, 4, 1000, false, 3 }, + { TYPE_DC, CH5, FLD_YD, UNIT_WH, 20, 2, 1, false, 0 }, + { TYPE_DC, CH5, FLD_IRR, UNIT_PCT, CALC_IRR_CH, CH0, CMD_CALC, false, 3 }, { TYPE_AC, CH0, FLD_UAC, UNIT_V, 74, 2, 10, false, 1 }, // dummy { TYPE_AC, CH0, FLD_UAC_1N, UNIT_V, 68, 2, 10, false, 1 }, diff --git a/platformio.ini b/platformio.ini index 382441db..ae2a623a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -14,8 +14,12 @@ extra_configs = platformio_override.ini [env] +; Make sure to NOT add any spaces in the custom_ci_action property +; (also the position in the file is important) +custom_ci_action = generic + framework = arduino -platform = espressif32@6.3.0 +platform = espressif32@6.3.1 build_flags = -DCOMPONENT_EMBED_FILES=webapp_dist/index.html.gz:webapp_dist/zones.json.gz:webapp_dist/favicon.ico:webapp_dist/js/app.js.gz @@ -30,8 +34,8 @@ lib_deps = https://github.com/yubox-node-org/ESPAsyncWebServer bblanchon/ArduinoJson @ ^6.21.2 https://github.com/bertmelis/espMqttClient.git#v1.4.3 - nrf24/RF24 @ ^1.4.5 - olikraus/U8g2 @ ^2.34.17 + nrf24/RF24 @ ^1.4.7 + olikraus/U8g2 @ ^2.34.18 buelowp/sunset @ ^1.1.7 extra_scripts = diff --git a/src/MqttHandleDtu.cpp b/src/MqttHandleDtu.cpp index dfca2340..ee5ad417 100644 --- a/src/MqttHandleDtu.cpp +++ b/src/MqttHandleDtu.cpp @@ -28,6 +28,7 @@ void MqttHandleDtuClass::loop() MqttSettings.publish("dtu/hostname", NetworkSettings.getHostname()); if (NetworkSettings.NetworkMode() == network_mode::WiFi) { MqttSettings.publish("dtu/rssi", String(WiFi.RSSI())); + MqttSettings.publish("dtu/bssid", String(WiFi.BSSIDstr())); } _lastPublish = millis(); diff --git a/src/MqttHandleInverter.cpp b/src/MqttHandleInverter.cpp index ed620dc8..a42803cd 100644 --- a/src/MqttHandleInverter.cpp +++ b/src/MqttHandleInverter.cpp @@ -129,7 +129,6 @@ void MqttHandleInverterClass::publishField(std::shared_ptr inv String value = String( inv->Statistics()->getChannelFieldValue(type, channel, fieldId), static_cast(inv->Statistics()->getChannelFieldDigits(type, channel, fieldId))); - value.trim(); MqttSettings.publish(topic, value); } diff --git a/src/MqttSettings.cpp b/src/MqttSettings.cpp index da0363df..d5b29faf 100644 --- a/src/MqttSettings.cpp +++ b/src/MqttSettings.cpp @@ -159,7 +159,11 @@ void MqttSettingsClass::publish(const String& subtopic, const String& payload) { String topic = getPrefix(); topic += subtopic; - mqttClient->publish(topic.c_str(), 0, Configuration.get().Mqtt_Retain, payload.c_str()); + + String value = payload; + value.trim(); + + mqttClient->publish(topic.c_str(), 0, Configuration.get().Mqtt_Retain, value.c_str()); } void MqttSettingsClass::publishGeneric(const String& topic, const String& payload, bool retain, uint8_t qos) diff --git a/src/WebApi_network.cpp b/src/WebApi_network.cpp index 06d8261e..1226917f 100644 --- a/src/WebApi_network.cpp +++ b/src/WebApi_network.cpp @@ -36,6 +36,7 @@ void WebApiNetworkClass::onNetworkStatus(AsyncWebServerRequest* request) root["sta_status"] = ((WiFi.getMode() & WIFI_STA) != 0); root["sta_ssid"] = WiFi.SSID(); + root["sta_bssid"] = WiFi.BSSIDstr(); root["sta_rssi"] = WiFi.RSSI(); root["network_hostname"] = NetworkSettings.getHostname(); root["network_ip"] = NetworkSettings.localIP().toString(); diff --git a/src/WebApi_ntp.cpp b/src/WebApi_ntp.cpp index 26524c2a..67b30851 100644 --- a/src/WebApi_ntp.cpp +++ b/src/WebApi_ntp.cpp @@ -55,14 +55,14 @@ void WebApiNtpClass::onNtpStatus(AsyncWebServerRequest* request) if (SunPosition.sunriseTime(&timeinfo)) { strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo); } else { - strcpy(timeStringBuff, "--"); + snprintf(timeStringBuff, sizeof(timeStringBuff), "--"); } root["sun_risetime"] = timeStringBuff; if (SunPosition.sunsetTime(&timeinfo)) { strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo); } else { - strcpy(timeStringBuff, "--"); + snprintf(timeStringBuff, sizeof(timeStringBuff), "--"); } root["sun_settime"] = timeStringBuff; diff --git a/src/WebApi_prometheus.cpp b/src/WebApi_prometheus.cpp index d921dac6..62f95c63 100644 --- a/src/WebApi_prometheus.cpp +++ b/src/WebApi_prometheus.cpp @@ -53,6 +53,10 @@ void WebApiPrometheusClass::onPrometheusMetricsGet(AsyncWebServerRequest* reques stream->print("# TYPE wifi_rssi gauge\n"); stream->printf("wifi_rssi %d\n", WiFi.RSSI()); + stream->print("# HELP wifi_bssid WiFi BSSID\n"); + stream->print("# TYPE wifi_bssid gauge\n"); + stream->printf("wifi_bssid %s\n", WiFi.BSSIDstr().c_str()); + for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { auto inv = Hoymiles.getInverterByPos(i); diff --git a/src/WebApi_ws_live.cpp b/src/WebApi_ws_live.cpp index 74db2bea..0213cc94 100644 --- a/src/WebApi_ws_live.cpp +++ b/src/WebApi_ws_live.cpp @@ -79,8 +79,10 @@ void WebApiWsLiveClass::loop() _ws.textAll(buffer); } - } catch (std::bad_alloc& bad_alloc) { + } catch (const std::bad_alloc& bad_alloc) { MessageOutput.printf("Call to /api/livedata/status temporarely out of resources. Reason: \"%s\".\r\n", bad_alloc.what()); + } catch (const std::exception& exc) { + MessageOutput.printf("Unknown exception in /api/livedata/status. Reason: \"%s\".\r\n", exc.what()); } _lastWsPublish = millis(); @@ -229,9 +231,11 @@ void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request) response->setLength(); request->send(response); - } catch (std::bad_alloc& bad_alloc) { + } catch (const std::bad_alloc& bad_alloc) { MessageOutput.printf("Call to /api/livedata/status temporarely out of resources. Reason: \"%s\".\r\n", bad_alloc.what()); - + WebApi.sendTooManyRequests(request); + } catch (const std::exception& exc) { + MessageOutput.printf("Unknown exception in /api/livedata/status. Reason: \"%s\".\r\n", exc.what()); WebApi.sendTooManyRequests(request); } } \ No newline at end of file diff --git a/webapp/package.json b/webapp/package.json index 7ae39f84..9431e2d5 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -23,7 +23,7 @@ }, "devDependencies": { "@intlify/unplugin-vue-i18n": "^0.11.0", - "@rushstack/eslint-patch": "^1.3.0", + "@rushstack/eslint-patch": "^1.3.1", "@tsconfig/node18": "^2.0.1", "@types/bootstrap": "^5.2.6", "@types/node": "^20.2.5", @@ -32,10 +32,10 @@ "@vitejs/plugin-vue": "^4.2.3", "@vue/eslint-config-typescript": "^11.0.3", "@vue/tsconfig": "^0.4.0", - "eslint": "^8.41.0", + "eslint": "^8.42.0", "eslint-plugin-vue": "^9.14.1", "npm-run-all": "^4.1.5", - "sass": "^1.62.1", + "sass": "^1.62.2", "terser": "^5.17.7", "typescript": "^5.1.3", "vite": "^4.3.9", diff --git a/webapp/src/components/WifiStationInfo.vue b/webapp/src/components/WifiStationInfo.vue index e1bd0dcd..12769a8e 100644 --- a/webapp/src/components/WifiStationInfo.vue +++ b/webapp/src/components/WifiStationInfo.vue @@ -13,6 +13,10 @@ {{ $t('wifistationinfo.Ssid') }} {{ networkStatus.sta_ssid }} + + {{ $t('wifistationinfo.Bssid') }} + {{ networkStatus.sta_bssid }} + {{ $t('wifistationinfo.Quality') }} {{ $n(getRSSIasQuality(networkStatus.sta_rssi), 'percent') }} diff --git a/webapp/src/locales/de.json b/webapp/src/locales/de.json index 0d454bae..a014f09d 100644 --- a/webapp/src/locales/de.json +++ b/webapp/src/locales/de.json @@ -208,6 +208,7 @@ "Enabled": "aktiv", "Disabled": "nicht aktiv", "Ssid": "SSID", + "Bssid": "BSSID", "Quality": "Qualität", "Rssi": "RSSI" }, diff --git a/webapp/src/locales/en.json b/webapp/src/locales/en.json index 7a05b4db..4532861b 100644 --- a/webapp/src/locales/en.json +++ b/webapp/src/locales/en.json @@ -208,6 +208,7 @@ "Enabled": "enabled", "Disabled": "disabled", "Ssid": "SSID", + "Bssid": "BSSID", "Quality": "Quality", "Rssi": "RSSI" }, diff --git a/webapp/src/locales/fr.json b/webapp/src/locales/fr.json index daafad70..86b517f5 100644 --- a/webapp/src/locales/fr.json +++ b/webapp/src/locales/fr.json @@ -208,6 +208,7 @@ "Enabled": "activé", "Disabled": "désactivé", "Ssid": "SSID", + "Bssid": "BSSID", "Quality": "Qualité", "Rssi": "RSSI" }, diff --git a/webapp/src/types/NetworkStatus.ts b/webapp/src/types/NetworkStatus.ts index c10c4a0f..90038c9d 100644 --- a/webapp/src/types/NetworkStatus.ts +++ b/webapp/src/types/NetworkStatus.ts @@ -2,6 +2,7 @@ export interface NetworkStatus { // WifiStationInfo sta_status: boolean; sta_ssid: string; + sta_bssid: string; sta_rssi: number; // WifiApInfo ap_status: boolean; diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 7a5d7d5c..5888d035 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -156,15 +156,15 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.41.0": - version "8.41.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.41.0.tgz#080321c3b68253522f7646b55b577dd99d2950b3" - integrity sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA== +"@eslint/js@8.42.0": + version "8.42.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.42.0.tgz#484a1d638de2911e6f5a30c12f49c7e4a3270fb6" + integrity sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw== -"@humanwhocodes/config-array@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" - integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== +"@humanwhocodes/config-array@^0.11.10": + version "0.11.10" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" + integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" @@ -345,10 +345,10 @@ estree-walker "^2.0.2" picomatch "^2.3.1" -"@rushstack/eslint-patch@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.3.0.tgz#f5635b36fc0dad96ef1e542a302cd914230188c0" - integrity sha512-IthPJsJR85GhOkp3Hvp8zFOPK5ynKn6STyHa/WZpioK7E1aYDiBzpqQPrngc14DszIUkIrdd3k9Iu0XSzlP/1w== +"@rushstack/eslint-patch@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.3.1.tgz#edbb85ff95f3be41eaa70c6d6ad6d8ba0a9c7e46" + integrity sha512-RkmuBcqiNioeeBKbgzMlOdreUkJfYaSjwgx9XDgGGpjvWgyaxWvDmZVSN9CS6LjEASadhgPv2BcFp+SeouWXXA== "@tsconfig/node18@^2.0.1": version "2.0.1" @@ -1184,16 +1184,16 @@ eslint-visitor-keys@^3.4.1: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== -eslint@^8.41.0: - version "8.41.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.41.0.tgz#3062ca73363b4714b16dbc1e60f035e6134b6f1c" - integrity sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q== +eslint@^8.42.0: + version "8.42.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.42.0.tgz#7bebdc3a55f9ed7167251fe7259f75219cade291" + integrity sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.4.0" "@eslint/eslintrc" "^2.0.3" - "@eslint/js" "8.41.0" - "@humanwhocodes/config-array" "^0.11.8" + "@eslint/js" "8.42.0" + "@humanwhocodes/config-array" "^0.11.10" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" ajv "^6.10.0" @@ -2220,10 +2220,10 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" -sass@^1.62.1: - version "1.62.1" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.62.1.tgz#caa8d6bf098935bc92fc73fa169fb3790cacd029" - integrity sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A== +sass@^1.62.2: + version "1.63.2" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.63.2.tgz#75f7d9a8e67d1d5b98a989507f4d98b6067b1f75" + integrity sha512-u56TU0AIFqMtauKl/OJ1AeFsXqRHkgO7nCWmHaDwfxDo9GUMSqBA4NEh6GMuh1CYVM7zuROYtZrHzPc2ixK+ww== dependencies: chokidar ">=3.0.0 <4.0.0" immutable "^4.0.0" diff --git a/webapp_dist/js/app.js.gz b/webapp_dist/js/app.js.gz index 47414dc3..05777db2 100644 Binary files a/webapp_dist/js/app.js.gz and b/webapp_dist/js/app.js.gz differ