Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge upstream v25.1.14 #1534

Merged
merged 44 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
33a9b74
Make function getClientId const
tbnobody Nov 10, 2024
d843ac6
Fix comment
tbnobody Nov 11, 2024
eac2e2f
Fix: Really always execute the generate of the factory.bin file
tbnobody Nov 11, 2024
2b07e3c
Organize includes
tbnobody Nov 12, 2024
9bfded0
Remove not required string generation
tbnobody Nov 13, 2024
cc3290b
Use correct variable
tbnobody Nov 13, 2024
8297591
change markdown table to github style
stefan123t Nov 20, 2024
680863f
Update README.md
stefan123t Nov 20, 2024
041ae7b
add Sum of DC Powrr
turrican944 Nov 22, 2024
37b1730
webapp: fix line break for reload button
schlimmchen Nov 11, 2024
b2dcac5
Fix: need to skip BOM also when migrating config
schlimmchen Nov 29, 2024
1c5a3cf
webapp: avoid undefined serial for InputSerial
schlimmchen Dec 1, 2024
a75543c
Feature:: Added support for HMS-450 inverters which begin with 1400
tbnobody Dec 2, 2024
241ee1e
webapp: Update dependencies
tbnobody Dec 2, 2024
8247070
webapp: improve styling of hints on home view
schlimmchen Dec 3, 2024
bf89fd7
webapp: Update dependencies
tbnobody Dec 5, 2024
1c1fcbe
Upgrade ESPAsyncWebServer from 3.3.22 to 3.3.23
tbnobody Dec 5, 2024
d775ee9
Update bblanchon/ArduinoJson from 7.2.0 to 7.2.1
tbnobody Dec 5, 2024
726a08e
Upgrade ESPAsyncWebServer from 3.3.23 to 3.4.0
tbnobody Dec 13, 2024
2edec64
Fix: Remove temperature readings for ESP32-S2 modules
tbnobody Dec 14, 2024
58382be
Feature: show hint if device profile missing or not selected
tbnobody Dec 14, 2024
5d14454
Fix: Auto reboot was not triggered on pin mapping change
tbnobody Dec 14, 2024
0061d5e
Upgrade ESPAsyncWebServer from 3.4.0 to 3.4.1
tbnobody Dec 15, 2024
8acae28
Feature: New handling of command queue
tbnobody Dec 14, 2024
5265c62
Feature: Set Limit transfer only to "OK" if the queue does not conta…
tbnobody Dec 15, 2024
24b3f27
webapp: Update dependencies
tbnobody Dec 16, 2024
940027a
Upgrade ESPAsyncWebServer from 3.4.1 to 3.4.2
tbnobody Dec 18, 2024
8f60a3a
Feature: Show inverter status and current power in overview (if multi…
tbnobody Dec 18, 2024
d485d1b
Show totals in blue and producing inverters in green
tbnobody Dec 18, 2024
96ba58a
Fix: Wifi.begin was called with wrong parameters
tbnobody Dec 18, 2024
c7fa4ff
Disable queue debugging
tbnobody Dec 21, 2024
1110594
Fix: Uptime overflow after ~50 days
tbnobody Dec 29, 2024
d43ac7f
Update bblanchon/ArduinoJson from 7.2.1 to 7.3.0
tbnobody Dec 29, 2024
498afe3
Remove extra semikolon
tbnobody Dec 29, 2024
c37397a
Fix lint errors
tbnobody Dec 29, 2024
a0e6942
Feature: Detect if inverter supports 'Power Distribution Logic'
tbnobody Dec 31, 2024
50207a4
webapp: Update dependencies
tbnobody Dec 31, 2024
87772cb
Feature: Add support for HERF-600 inverters
tbnobody Jan 8, 2025
19fa310
webapp: Update dependencies
tbnobody Jan 14, 2025
d068542
Merge branch 'pr2421' into dev
tbnobody Jan 14, 2025
ebf4e92
Merge branch 'pr2420' into dev
tbnobody Jan 14, 2025
5510c9f
webapp: add app.js.gz
tbnobody Jan 14, 2025
b233840
Merge upstream tag 'v25.1.14'
AndreasBoehm Jan 14, 2025
13904a4
Fix: live card header bg matches upstream color
AndreasBoehm Jan 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/MqttSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class MqttSettingsClass {
void unsubscribe(const String& topic);

String getPrefix() const;
String getClientId();
String getClientId() const;

private:
void NetworkEvent(network_event event);
Expand Down
12 changes: 9 additions & 3 deletions lang/es.lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@
"Refreshing": "Refrescando",
"Pull": "Tira hacia abajo para refrescar",
"Release": "Soltar para refrescar",
"Close": "Cerrar"
"Close": "Cerrar",
"Yes": "Yes",
"No": "No"
},
"wait": {
"NotReady": "OpenDTU is not yet ready",
Expand Down Expand Up @@ -193,7 +195,10 @@
"FirmwareVersion": "Versión del firmware",
"FirmwareBuildDate": "Fecha de construcción del firmware",
"HardwarePartNumber": "Número de parte de hardware",
"HardwareVersion": "Versión de hardware"
"HardwareVersion": "Versión de hardware",
"SupportsPowerDistributionLogic": "'Power Distribution Logic' supported",
"Yes": "@:base.Yes",
"No": "@:base.No"
},
"gridprofile": {
"NoInfo": "@:devinfo.NoInfo",
Expand Down Expand Up @@ -637,7 +642,8 @@
"TimeSync": "El reloj aún no ha sido sincronizado. Sin un reloj correctamente ajustado, no se realizan solicitudes al inversor. Esto es normal poco después del inicio. Sin embargo, después de un tiempo de ejecución más largo (>1 minuto), indica que el servidor NTP no es accesible.",
"TimeSyncLink": "Por favor, verifica la configuración de tu hora.",
"DefaultPassword": "Estás utilizando la contraseña predeterminada para la interfaz web y el punto de acceso de emergencia. Esto potencialmente es inseguro.",
"DefaultPasswordLink": "Por favor, cambia la contraseña."
"DefaultPasswordLink": "Por favor, cambia la contraseña.",
"PinMappingIssue": "You are using a generic firmware image, but have not yet uploaded a file with device profiles (<code>pin_mapping.json</code>) or have not selected a profile defined there. Please refer to the <a href=\"https://opendtu-onbattery.net/firmware/device_profiles/\" target=\"_blank\" class=\"alert-link\">documentation</a> for details."
},
"deviceadmin": {
"DeviceManager": "Administrador de Dispositivos",
Expand Down
12 changes: 9 additions & 3 deletions lang/it.lang.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@
"Refreshing": "Aggiorna",
"Pull": "Trascina in basso per aggiornare",
"Release": "Rilascia per aggiornare",
"Close": "Chiudi"
"Close": "Chiudi",
"Yes": "Yes",
"No": "No"
},
"wait": {
"NotReady": "OpenDTU is not yet ready",
Expand Down Expand Up @@ -193,7 +195,10 @@
"FirmwareVersion": "Versione Firmware",
"FirmwareBuildDate": "Data Firmware",
"HardwarePartNumber": "Hardware Part Number",
"HardwareVersion": "Hardware Version"
"HardwareVersion": "Hardware Version",
"SupportsPowerDistributionLogic": "'Power Distribution Logic' supported",
"Yes": "@:base.Yes",
"No": "@:base.No"
},
"gridprofile": {
"NoInfo": "@:devinfo.NoInfo",
Expand Down Expand Up @@ -637,7 +642,8 @@
"TimeSync": "La Data/Ora non sono state sincronizzate, ed in tal caso non è possibile eseguire richieste all'inverter. Questa condizione è normale appena avviato, tuttavia dopo un po' (>1 minuto), questa situazione potrebbe indicare un problema di accesso al server NTP.",
"TimeSyncLink": "Controlla le impostazioni Data/Ora.",
"DefaultPassword": "Stai usando la password di default per accedere all'interfaccia web e per la modalità Access Point di emergenza. Questo può portare ad un rischio di sicurezza.",
"DefaultPasswordLink": "Per favore cambia la password."
"DefaultPasswordLink": "Per favore cambia la password.",
"PinMappingIssue": "You are using a generic firmware image, but have not yet uploaded a file with device profiles (<code>pin_mapping.json</code>) or have not selected a profile defined there. Please refer to the <a href=\"https://opendtu-onbattery.net/firmware/device_profiles/\" target=\"_blank\" class=\"alert-link\">documentation</a> for details."
},
"deviceadmin": {
"DeviceManager": "Device-Manager",
Expand Down
6 changes: 6 additions & 0 deletions lib/CpuTemperature/src/CpuTemperature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ CpuTemperatureClass CpuTemperature;

float CpuTemperatureClass::read()
{
#ifdef CONFIG_IDF_TARGET_ESP32S2
// Disabling temperature reading for ESP32-S2 models as it might lead to WDT resets.
// See: https://github.com/espressif/esp-idf/issues/8088
return NAN;
#endif

std::lock_guard<std::mutex> lock(_mutex);

float temperature = NAN;
Expand Down
4 changes: 3 additions & 1 deletion lib/Hoymiles/src/Hoymiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void HoymilesClass::loop()
}
}

if (iv != nullptr && iv->getRadio()->isInitialized() && iv->getRadio()->isQueueEmpty()) {
if (iv != nullptr && iv->getRadio()->isInitialized()) {

if (iv->getZeroValuesIfUnreachable() && !iv->isReachable()) {
iv->Statistics()->zeroRuntimeData();
Expand Down Expand Up @@ -119,6 +119,7 @@ void HoymilesClass::loop()
iv->sendGridOnProFileParaRequest();
}

_messageOutput->printf("Queue size - NRF: %" PRId32 " CMT: %" PRId32 "\r\n", _radioNrf->getQueueSize(), _radioCmt->getQueueSize());
_lastPoll = millis();
}

Expand Down Expand Up @@ -229,6 +230,7 @@ void HoymilesClass::removeInverterBySerial(const uint64_t serial)
for (uint8_t i = 0; i < _inverters.size(); i++) {
if (_inverters[i]->serial() == serial) {
std::lock_guard<std::mutex> lock(_mutex);
_inverters[i]->getRadio()->removeCommands(_inverters[i].get());
_inverters.erase(_inverters.begin() + i);
return;
}
Expand Down
15 changes: 15 additions & 0 deletions lib/Hoymiles/src/HoymilesRadio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ bool HoymilesRadio::isInitialized() const
return _isInitialized;
}

void HoymilesRadio::removeCommands(InverterAbstract* inv)
{
_commandQueue.removeAllEntriesForInverter(inv);
}

uint8_t HoymilesRadio::countSimilarCommands(std::shared_ptr<CommandAbstract> cmd)
{
return _commandQueue.countSimilarCommands(cmd);
}

bool HoymilesRadio::isIdle() const
{
return !_busyFlag;
Expand All @@ -165,3 +175,8 @@ bool HoymilesRadio::isQueueEmpty() const
{
return _commandQueue.size() == 0;
}

uint32_t HoymilesRadio::getQueueSize() const
{
return _commandQueue.size();
}
49 changes: 46 additions & 3 deletions lib/Hoymiles/src/HoymilesRadio.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#include "Arduino.h"
#include "commands/CommandAbstract.h"
#include "queue/CommandQueue.h"
#include "types.h"
#include <ThreadSafeQueue.h>
#include <TimeoutHelper.h>
#include <memory>

#ifdef HOY_DEBUG_QUEUE
#define DEBUG_PRINT(fmt, args...) Serial.printf(fmt, ##args)
#else
#define DEBUG_PRINT(fmt, args...) /* Don't do anything in release builds */
#endif

class HoymilesRadio {
public:
Expand All @@ -14,11 +20,48 @@ class HoymilesRadio {

bool isIdle() const;
bool isQueueEmpty() const;
uint32_t getQueueSize() const;
bool isInitialized() const;

void removeCommands(InverterAbstract* inv);
uint8_t countSimilarCommands(std::shared_ptr<CommandAbstract> cmd);

void enqueCommand(std::shared_ptr<CommandAbstract> cmd)
{
DEBUG_PRINT("Queue size before: %ld\r\n", _commandQueue.size());
DEBUG_PRINT("Handling command %s with type %d\r\n", cmd.get()->getCommandName().c_str(), static_cast<uint8_t>(cmd.get()->getQueueInsertType()));
switch (cmd.get()->getQueueInsertType()) {
case QueueInsertType::RemoveOldest:
_commandQueue.removeDuplicatedEntries(cmd);
break;
case QueueInsertType::ReplaceExistent:
// Checks if the queue already contains a command like the new one
// and replaces the existing one with the new one.
// (The new one will not be pushed at the end of the queue)
if (_commandQueue.countSimilarCommands(cmd) > 0) {
DEBUG_PRINT(" ... existing entry will be replaced\r\n");
_commandQueue.replaceEntries(cmd);
return;
}
break;
case QueueInsertType::RemoveNewest:
// Checks if the queue already contains a command like the new one
// and drops the new one. The new one will not be inserted.
if (_commandQueue.countSimilarCommands(cmd) > 0) {
DEBUG_PRINT(" ... new entry will be dropped\r\n");
return;
}
break;
case QueueInsertType::AllowMultiple:
// Dont do anything, just fall through and insert the command.
break;
}

// Push the command into the queue if we reach this position of the code
DEBUG_PRINT(" ... new entry will be appended\r\n");
_commandQueue.push(cmd);

DEBUG_PRINT("Queue size after: %ld\r\n", _commandQueue.size());
}

template <typename T>
Expand All @@ -38,7 +81,7 @@ class HoymilesRadio {
void handleReceivedPackage();

serial_u _dtuSerial;
ThreadSafeQueue<std::shared_ptr<CommandAbstract>> _commandQueue;
CommandQueue _commandQueue;
bool _isInitialized = false;
bool _busyFlag = false;

Expand Down
17 changes: 14 additions & 3 deletions lib/Hoymiles/src/commands/ActivePowerControlCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,15 @@ ActivePowerControlCommand::ActivePowerControlCommand(InverterAbstract* inv, cons

String ActivePowerControlCommand::getCommandName() const
{
return "ActivePowerControl";
char buffer[30];
snprintf(buffer, sizeof(buffer), "ActivePowerControl (%02X)", getType());
return buffer;
}

bool ActivePowerControlCommand::areSameParameter(CommandAbstract* other)
{
return CommandAbstract::areSameParameter(other)
&& this->getType() == static_cast<ActivePowerControlCommand*>(other)->getType();
}

void ActivePowerControlCommand::setActivePowerLimit(const float limit, const PowerLimitControlType type)
Expand Down Expand Up @@ -79,7 +87,10 @@ bool ActivePowerControlCommand::handleResponse(const fragment_t fragment[], cons
}
}
_inv->SystemConfigPara()->setLastUpdateCommand(millis());
_inv->SystemConfigPara()->setLastLimitCommandSuccess(CMD_OK);
std::shared_ptr<ActivePowerControlCommand> cmd(std::shared_ptr<ActivePowerControlCommand>(), this);
if (_inv->getRadio()->countSimilarCommands(cmd) == 1) {
_inv->SystemConfigPara()->setLastLimitCommandSuccess(CMD_OK);
}
return true;
}

Expand All @@ -89,7 +100,7 @@ float ActivePowerControlCommand::getLimit() const
return l / 10;
}

PowerLimitControlType ActivePowerControlCommand::getType()
PowerLimitControlType ActivePowerControlCommand::getType() const
{
return (PowerLimitControlType)((static_cast<uint16_t>(_payload[14]) << 8) | _payload[15]);
}
Expand Down
4 changes: 3 additions & 1 deletion lib/Hoymiles/src/commands/ActivePowerControlCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ class ActivePowerControlCommand : public DevControlCommand {
explicit ActivePowerControlCommand(InverterAbstract* inv, const uint64_t router_address = 0);

virtual String getCommandName() const;
virtual QueueInsertType getQueueInsertType() const { return QueueInsertType::RemoveOldest; }
virtual bool areSameParameter(CommandAbstract* other);

virtual bool handleResponse(const fragment_t fragment[], const uint8_t max_fragment_id);
virtual void gotTimeout();

void setActivePowerLimit(const float limit, const PowerLimitControlType type = RelativNonPersistent);
float getLimit() const;
PowerLimitControlType getType();
PowerLimitControlType getType() const;
};
6 changes: 6 additions & 0 deletions lib/Hoymiles/src/commands/CommandAbstract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,9 @@ uint8_t CommandAbstract::getMaxRetransmitCount() const
{
return MAX_RETRANSMIT_COUNT;
}

bool CommandAbstract::areSameParameter(CommandAbstract* other)
{
return this->getCommandName() == other->getCommandName()
&& this->_targetAddress == other->getTargetAddress();
}
16 changes: 16 additions & 0 deletions lib/Hoymiles/src/commands/CommandAbstract.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@

class InverterAbstract;

enum class QueueInsertType {
AllowMultiple,
// Remove from beginning of the queue
RemoveOldest,

// Don't insert command if it already exist
RemoveNewest,

// Replace the existing entry in the queue by the one to be added
ReplaceExistent,
};

class CommandAbstract {
public:
explicit CommandAbstract(InverterAbstract* inv, const uint64_t router_address = 0);
Expand Down Expand Up @@ -46,6 +58,10 @@ class CommandAbstract {
// Sets the amount how often a missing fragment is re-requested if it was not available
virtual uint8_t getMaxRetransmitCount() const;

// Returns whether multiple instances of this command are allowed in the command queue.
virtual QueueInsertType getQueueInsertType() const { return QueueInsertType::RemoveNewest; }
virtual bool areSameParameter(CommandAbstract* other);

protected:
uint8_t _payload[RF_LEN];
uint8_t _payload_size;
Expand Down
1 change: 1 addition & 0 deletions lib/Hoymiles/src/commands/PowerControlCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class PowerControlCommand : public DevControlCommand {
explicit PowerControlCommand(InverterAbstract* inv, const uint64_t router_address = 0);

virtual String getCommandName() const;
virtual QueueInsertType getQueueInsertType() const { return QueueInsertType::AllowMultiple; }

virtual bool handleResponse(const fragment_t fragment[], const uint8_t max_fragment_id);
virtual void gotTimeout();
Expand Down
4 changes: 3 additions & 1 deletion lib/Hoymiles/src/inverters/HERF_1CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ static const channelMetaData_t channelMetaData[] = {
};

HERF_1CH::HERF_1CH(HoymilesRadio* radio, const uint64_t serial)
: HM_Abstract(radio, serial) {};
: HM_Abstract(radio, serial)
{
}

bool HERF_1CH::isValidSerial(const uint64_t serial)
{
Expand Down
6 changes: 4 additions & 2 deletions lib/Hoymiles/src/inverters/HERF_2CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ static const channelMetaData_t channelMetaData[] = {
};

HERF_2CH::HERF_2CH(HoymilesRadio* radio, const uint64_t serial)
: HM_Abstract(radio, serial) {};
: HM_Abstract(radio, serial)
{
}

bool HERF_2CH::isValidSerial(const uint64_t serial)
{
Expand All @@ -53,7 +55,7 @@ bool HERF_2CH::isValidSerial(const uint64_t serial)

String HERF_2CH::typeName() const
{
return "HERF-800-2T";
return "HERF-600/800-2T";
}

const byteAssign_t* HERF_2CH::getByteAssignment() const
Expand Down
4 changes: 3 additions & 1 deletion lib/Hoymiles/src/inverters/HERF_4CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#include "HERF_4CH.h"

HERF_4CH::HERF_4CH(HoymilesRadio* radio, const uint64_t serial)
: HM_4CH(radio, serial) {};
: HM_4CH(radio, serial)
{
}

bool HERF_4CH::isValidSerial(const uint64_t serial)
{
Expand Down
4 changes: 3 additions & 1 deletion lib/Hoymiles/src/inverters/HMS_1CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ static const channelMetaData_t channelMetaData[] = {
};

HMS_1CH::HMS_1CH(HoymilesRadio* radio, const uint64_t serial)
: HMS_Abstract(radio, serial) {};
: HMS_Abstract(radio, serial)
{
}

bool HMS_1CH::isValidSerial(const uint64_t serial)
{
Expand Down
8 changes: 5 additions & 3 deletions lib/Hoymiles/src/inverters/HMS_1CHv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,20 @@ static const channelMetaData_t channelMetaData[] = {
};

HMS_1CHv2::HMS_1CHv2(HoymilesRadio* radio, const uint64_t serial)
: HMS_Abstract(radio, serial) {};
: HMS_Abstract(radio, serial)
{
}

bool HMS_1CHv2::isValidSerial(const uint64_t serial)
{
// serial >= 0x112500000000 && serial <= 0x1125ffffffff
uint16_t preSerial = (serial >> 32) & 0xffff;
return preSerial == 0x1125;
return preSerial == 0x1125 || preSerial == 0x1400;
}

String HMS_1CHv2::typeName() const
{
return "HMS-500-1T v2";
return "HMS-450/500-1T v2";
}

const byteAssign_t* HMS_1CHv2::getByteAssignment() const
Expand Down
Loading
Loading