Feature: Allow setting of the Reachable Threshold per inverter
This commit is contained in:
parent
c5f9f460cd
commit
2c41be106e
@ -45,6 +45,7 @@ struct INVERTER_CONFIG_T {
|
|||||||
bool Poll_Enable_Night;
|
bool Poll_Enable_Night;
|
||||||
bool Command_Enable;
|
bool Command_Enable;
|
||||||
bool Command_Enable_Night;
|
bool Command_Enable_Night;
|
||||||
|
uint8_t ReachableThreshold;
|
||||||
CHANNEL_CONFIG_T channel[INV_MAX_CHAN_COUNT];
|
CHANNEL_CONFIG_T channel[INV_MAX_CHAN_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -94,4 +94,6 @@
|
|||||||
#define DISPLAY_SCREENSAVER true
|
#define DISPLAY_SCREENSAVER true
|
||||||
#define DISPLAY_ROTATION 2U
|
#define DISPLAY_ROTATION 2U
|
||||||
#define DISPLAY_CONTRAST 60U
|
#define DISPLAY_CONTRAST 60U
|
||||||
#define DISPLAY_LANGUAGE 0U
|
#define DISPLAY_LANGUAGE 0U
|
||||||
|
|
||||||
|
#define REACHABLE_THRESHOLD 2U
|
||||||
@ -73,7 +73,7 @@ bool InverterAbstract::isProducing()
|
|||||||
|
|
||||||
bool InverterAbstract::isReachable()
|
bool InverterAbstract::isReachable()
|
||||||
{
|
{
|
||||||
return _enablePolling && Statistics()->getRxFailureCount() <= MAX_ONLINE_FAILURE_COUNT;
|
return _enablePolling && Statistics()->getRxFailureCount() <= _reachableThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InverterAbstract::setEnablePolling(bool enabled)
|
void InverterAbstract::setEnablePolling(bool enabled)
|
||||||
@ -96,6 +96,16 @@ bool InverterAbstract::getEnableCommands()
|
|||||||
return _enableCommands;
|
return _enableCommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InverterAbstract::setReachableThreshold(uint8_t threshold)
|
||||||
|
{
|
||||||
|
_reachableThreshold = threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t InverterAbstract::getReachableThreshold()
|
||||||
|
{
|
||||||
|
return _reachableThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
bool InverterAbstract::sendChangeChannelRequest()
|
bool InverterAbstract::sendChangeChannelRequest()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -24,7 +24,6 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_RF_FRAGMENT_COUNT 13
|
#define MAX_RF_FRAGMENT_COUNT 13
|
||||||
#define MAX_ONLINE_FAILURE_COUNT 2
|
|
||||||
|
|
||||||
class CommandAbstract;
|
class CommandAbstract;
|
||||||
|
|
||||||
@ -49,6 +48,9 @@ public:
|
|||||||
void setEnableCommands(bool enabled);
|
void setEnableCommands(bool enabled);
|
||||||
bool getEnableCommands();
|
bool getEnableCommands();
|
||||||
|
|
||||||
|
void setReachableThreshold(uint8_t threshold);
|
||||||
|
uint8_t getReachableThreshold();
|
||||||
|
|
||||||
void clearRxFragmentBuffer();
|
void clearRxFragmentBuffer();
|
||||||
void addRxFragment(uint8_t fragment[], uint8_t len);
|
void addRxFragment(uint8_t fragment[], uint8_t len);
|
||||||
uint8_t verifyAllFragments(CommandAbstract* cmd);
|
uint8_t verifyAllFragments(CommandAbstract* cmd);
|
||||||
@ -87,6 +89,8 @@ private:
|
|||||||
bool _enablePolling = true;
|
bool _enablePolling = true;
|
||||||
bool _enableCommands = true;
|
bool _enableCommands = true;
|
||||||
|
|
||||||
|
uint8_t _reachableThreshold = 3;
|
||||||
|
|
||||||
std::unique_ptr<AlarmLogParser> _alarmLogParser;
|
std::unique_ptr<AlarmLogParser> _alarmLogParser;
|
||||||
std::unique_ptr<DevInfoParser> _devInfoParser;
|
std::unique_ptr<DevInfoParser> _devInfoParser;
|
||||||
std::unique_ptr<PowerCommandParser> _powerCommandParser;
|
std::unique_ptr<PowerCommandParser> _powerCommandParser;
|
||||||
|
|||||||
@ -110,6 +110,7 @@ bool ConfigurationClass::write()
|
|||||||
inv["poll_enable_night"] = config.Inverter[i].Poll_Enable_Night;
|
inv["poll_enable_night"] = config.Inverter[i].Poll_Enable_Night;
|
||||||
inv["command_enable"] = config.Inverter[i].Command_Enable;
|
inv["command_enable"] = config.Inverter[i].Command_Enable;
|
||||||
inv["command_enable_night"] = config.Inverter[i].Command_Enable_Night;
|
inv["command_enable_night"] = config.Inverter[i].Command_Enable_Night;
|
||||||
|
inv["reachable_threshold"] = config.Inverter[i].ReachableThreshold;
|
||||||
|
|
||||||
JsonArray channel = inv.createNestedArray("channel");
|
JsonArray channel = inv.createNestedArray("channel");
|
||||||
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
||||||
@ -258,6 +259,7 @@ bool ConfigurationClass::read()
|
|||||||
config.Inverter[i].Poll_Enable_Night = inv["poll_enable_night"] | true;
|
config.Inverter[i].Poll_Enable_Night = inv["poll_enable_night"] | true;
|
||||||
config.Inverter[i].Command_Enable = inv["command_enable"] | true;
|
config.Inverter[i].Command_Enable = inv["command_enable"] | true;
|
||||||
config.Inverter[i].Command_Enable_Night = inv["command_enable_night"] | true;
|
config.Inverter[i].Command_Enable_Night = inv["command_enable_night"] | true;
|
||||||
|
config.Inverter[i].ReachableThreshold = inv["reachable_threshold"] | REACHABLE_THRESHOLD;
|
||||||
|
|
||||||
JsonArray channel = inv["channel"];
|
JsonArray channel = inv["channel"];
|
||||||
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
||||||
|
|||||||
@ -71,6 +71,7 @@ void InverterSettingsClass::init()
|
|||||||
config.Inverter[i].Serial);
|
config.Inverter[i].Serial);
|
||||||
|
|
||||||
if (inv != nullptr) {
|
if (inv != nullptr) {
|
||||||
|
inv->setReachableThreshold(config.Inverter[i].ReachableThreshold);
|
||||||
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
||||||
inv->Statistics()->setStringMaxPower(c, config.Inverter[i].channel[c].MaxChannelPower);
|
inv->Statistics()->setStringMaxPower(c, config.Inverter[i].channel[c].MaxChannelPower);
|
||||||
inv->Statistics()->setChannelFieldOffset(TYPE_DC, static_cast<ChannelNum_t>(c), FLD_YT, config.Inverter[i].channel[c].YieldTotalOffset);
|
inv->Statistics()->setChannelFieldOffset(TYPE_DC, static_cast<ChannelNum_t>(c), FLD_YT, config.Inverter[i].channel[c].YieldTotalOffset);
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "MqttHandleHass.h"
|
#include "MqttHandleHass.h"
|
||||||
#include "WebApi.h"
|
#include "WebApi.h"
|
||||||
#include "WebApi_errors.h"
|
#include "WebApi_errors.h"
|
||||||
|
#include "defaults.h"
|
||||||
#include "helper.h"
|
#include "helper.h"
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
#include <Hoymiles.h>
|
#include <Hoymiles.h>
|
||||||
@ -57,6 +58,7 @@ void WebApiInverterClass::onInverterList(AsyncWebServerRequest* request)
|
|||||||
obj["poll_enable_night"] = config.Inverter[i].Poll_Enable_Night;
|
obj["poll_enable_night"] = config.Inverter[i].Poll_Enable_Night;
|
||||||
obj["command_enable"] = config.Inverter[i].Command_Enable;
|
obj["command_enable"] = config.Inverter[i].Command_Enable;
|
||||||
obj["command_enable_night"] = config.Inverter[i].Command_Enable_Night;
|
obj["command_enable_night"] = config.Inverter[i].Command_Enable_Night;
|
||||||
|
obj["reachable_threshold"] = config.Inverter[i].ReachableThreshold;
|
||||||
|
|
||||||
auto inv = Hoymiles.getInverterBySerial(config.Inverter[i].Serial);
|
auto inv = Hoymiles.getInverterBySerial(config.Inverter[i].Serial);
|
||||||
uint8_t max_channels;
|
uint8_t max_channels;
|
||||||
@ -281,6 +283,7 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
|||||||
inverter.Poll_Enable_Night = root["poll_enable_night"] | true;
|
inverter.Poll_Enable_Night = root["poll_enable_night"] | true;
|
||||||
inverter.Command_Enable = root["command_enable"] | true;
|
inverter.Command_Enable = root["command_enable"] | true;
|
||||||
inverter.Command_Enable_Night = root["command_enable_night"] | true;
|
inverter.Command_Enable_Night = root["command_enable_night"] | true;
|
||||||
|
inverter.ReachableThreshold = root["reachable_threshold"] | REACHABLE_THRESHOLD;
|
||||||
|
|
||||||
arrayCount++;
|
arrayCount++;
|
||||||
}
|
}
|
||||||
@ -311,6 +314,7 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
|||||||
if (inv != nullptr) {
|
if (inv != nullptr) {
|
||||||
inv->setEnablePolling(inverter.Poll_Enable);
|
inv->setEnablePolling(inverter.Poll_Enable);
|
||||||
inv->setEnableCommands(inverter.Command_Enable);
|
inv->setEnableCommands(inverter.Command_Enable);
|
||||||
|
inv->setReachableThreshold(inverter.ReachableThreshold);
|
||||||
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
||||||
inv->Statistics()->setStringMaxPower(c, inverter.channel[c].MaxChannelPower);
|
inv->Statistics()->setStringMaxPower(c, inverter.channel[c].MaxChannelPower);
|
||||||
inv->Statistics()->setChannelFieldOffset(TYPE_DC, static_cast<ChannelNum_t>(c), FLD_YT, inverter.channel[c].YieldTotalOffset);
|
inv->Statistics()->setChannelFieldOffset(TYPE_DC, static_cast<ChannelNum_t>(c), FLD_YT, inverter.channel[c].YieldTotalOffset);
|
||||||
|
|||||||
@ -454,6 +454,7 @@
|
|||||||
"EditInverter": "Wechselrichter bearbeiten",
|
"EditInverter": "Wechselrichter bearbeiten",
|
||||||
"General": "Allgemein",
|
"General": "Allgemein",
|
||||||
"String": "String",
|
"String": "String",
|
||||||
|
"Advanced": "Erweitert",
|
||||||
"InverterSerial": "Wechselrichter Seriennummer:",
|
"InverterSerial": "Wechselrichter Seriennummer:",
|
||||||
"InverterName": "Wechselrichter Name:",
|
"InverterName": "Wechselrichter Name:",
|
||||||
"InverterNameHint": "Hier kann ein eigener Namen für den Wechselrichter angeben werden.",
|
"InverterNameHint": "Hier kann ein eigener Namen für den Wechselrichter angeben werden.",
|
||||||
@ -469,6 +470,8 @@
|
|||||||
"StringYtOffset": "Ertragsversatz String {num}:",
|
"StringYtOffset": "Ertragsversatz String {num}:",
|
||||||
"StringYtOffsetHint": "Dieser Offset wird beim Auslesen des Gesamtertragswertes des Wechselrichters angewendet. Damit kann der Gesamtertrag des Wechselrichters auf Null gesetzt werden, wenn ein gebrauchter Wechselrichter verwendet wird.",
|
"StringYtOffsetHint": "Dieser Offset wird beim Auslesen des Gesamtertragswertes des Wechselrichters angewendet. Damit kann der Gesamtertrag des Wechselrichters auf Null gesetzt werden, wenn ein gebrauchter Wechselrichter verwendet wird.",
|
||||||
"InverterHint": "*) Geben Sie die W<sub>p</sub> des Ports ein, um die Einstrahlung zu errechnen.",
|
"InverterHint": "*) Geben Sie die W<sub>p</sub> des Ports ein, um die Einstrahlung zu errechnen.",
|
||||||
|
"ReachableThreshold": "Erreichbarkeit Schwellenwert:",
|
||||||
|
"ReachableThresholdHint": "Legt fest, wie viele Anfragen fehlschlagen dürfen, bis der Wechselrichter als unerreichbar eingestuft wird.",
|
||||||
"Cancel": "@:maintenancereboot.Cancel",
|
"Cancel": "@:maintenancereboot.Cancel",
|
||||||
"Save": "@:dtuadmin.Save",
|
"Save": "@:dtuadmin.Save",
|
||||||
"DeleteMsg": "Soll der Wechselrichter \"{name}\" mit der Seriennummer {serial} wirklich gelöscht werden?",
|
"DeleteMsg": "Soll der Wechselrichter \"{name}\" mit der Seriennummer {serial} wirklich gelöscht werden?",
|
||||||
|
|||||||
@ -454,6 +454,7 @@
|
|||||||
"EditInverter": "Edit inverter",
|
"EditInverter": "Edit inverter",
|
||||||
"General": "General",
|
"General": "General",
|
||||||
"String": "String",
|
"String": "String",
|
||||||
|
"Advanced": "Advanced",
|
||||||
"InverterSerial": "Inverter Serial:",
|
"InverterSerial": "Inverter Serial:",
|
||||||
"InverterName": "Inverter Name:",
|
"InverterName": "Inverter Name:",
|
||||||
"InverterNameHint": "Here you can specify a custom name for your inverter.",
|
"InverterNameHint": "Here you can specify a custom name for your inverter.",
|
||||||
@ -469,6 +470,8 @@
|
|||||||
"StringYtOffset": "Yield total offset string {num}:",
|
"StringYtOffset": "Yield total offset string {num}:",
|
||||||
"StringYtOffsetHint": "This offset is applied the read yield total value from the inverter. This can be used to set the yield total of the inverter to zero if a used inverter is used. But you can still try polling data.",
|
"StringYtOffsetHint": "This offset is applied the read yield total value from the inverter. This can be used to set the yield total of the inverter to zero if a used inverter is used. But you can still try polling data.",
|
||||||
"InverterHint": "*) Enter the W<sub>p</sub> of the channel to calculate irradiation.",
|
"InverterHint": "*) Enter the W<sub>p</sub> of the channel to calculate irradiation.",
|
||||||
|
"ReachableThreshold": "Reachable Threshold:",
|
||||||
|
"ReachableThresholdHint": "Defines how many requests are allowed to fail until the inverter is treated is not reachable.",
|
||||||
"Cancel": "@:maintenancereboot.Cancel",
|
"Cancel": "@:maintenancereboot.Cancel",
|
||||||
"Save": "@:dtuadmin.Save",
|
"Save": "@:dtuadmin.Save",
|
||||||
"DeleteMsg": "Are you sure you want to delete the inverter \"{name}\" with serial number {serial}?",
|
"DeleteMsg": "Are you sure you want to delete the inverter \"{name}\" with serial number {serial}?",
|
||||||
|
|||||||
@ -454,6 +454,7 @@
|
|||||||
"EditInverter": "Modifier l'onduleur",
|
"EditInverter": "Modifier l'onduleur",
|
||||||
"General": "Général",
|
"General": "Général",
|
||||||
"String": "Ligne",
|
"String": "Ligne",
|
||||||
|
"Advanced": "Advanced",
|
||||||
"InverterSerial": "Numéro de série de l'onduleur",
|
"InverterSerial": "Numéro de série de l'onduleur",
|
||||||
"InverterName": "Nom de l'onduleur :",
|
"InverterName": "Nom de l'onduleur :",
|
||||||
"InverterNameHint": "Ici, vous pouvez spécifier un nom personnalisé pour votre onduleur.",
|
"InverterNameHint": "Ici, vous pouvez spécifier un nom personnalisé pour votre onduleur.",
|
||||||
@ -469,6 +470,8 @@
|
|||||||
"StringYtOffset": "Décalage du rendement total de la ligne {num} :",
|
"StringYtOffset": "Décalage du rendement total de la ligne {num} :",
|
||||||
"StringYtOffsetHint": "Ce décalage est appliqué à la valeur de rendement total lue sur le variateur. Il peut être utilisé pour mettre le rendement total du variateur à zéro si un variateur usagé est utilisé.",
|
"StringYtOffsetHint": "Ce décalage est appliqué à la valeur de rendement total lue sur le variateur. Il peut être utilisé pour mettre le rendement total du variateur à zéro si un variateur usagé est utilisé.",
|
||||||
"InverterHint": "*) Entrez le W<sub>p</sub> du canal pour calculer l'irradiation.",
|
"InverterHint": "*) Entrez le W<sub>p</sub> du canal pour calculer l'irradiation.",
|
||||||
|
"ReachableThreshold": "Reachable Threshold:",
|
||||||
|
"ReachableThresholdHint": "Defines how many requests are allowed to fail until the inverter is treated is not reachable.",
|
||||||
"Cancel": "@:maintenancereboot.Cancel",
|
"Cancel": "@:maintenancereboot.Cancel",
|
||||||
"Save": "@:dtuadmin.Save",
|
"Save": "@:dtuadmin.Save",
|
||||||
"DeleteMsg": "Êtes-vous sûr de vouloir supprimer l'onduleur \"{name}\" avec le numéro de série \"{serial}\" ?",
|
"DeleteMsg": "Êtes-vous sûr de vouloir supprimer l'onduleur \"{name}\" avec le numéro de série \"{serial}\" ?",
|
||||||
|
|||||||
@ -88,6 +88,8 @@
|
|||||||
}}</button>
|
}}</button>
|
||||||
<button class="nav-link" id="nav-string-tab" data-bs-toggle="tab" data-bs-target="#nav-string"
|
<button class="nav-link" id="nav-string-tab" data-bs-toggle="tab" data-bs-target="#nav-string"
|
||||||
type="button" role="tab" aria-controls="nav-string">{{ $t('inverteradmin.String') }}</button>
|
type="button" role="tab" aria-controls="nav-string">{{ $t('inverteradmin.String') }}</button>
|
||||||
|
<button class="nav-link" id="nav-advanced-tab" data-bs-toggle="tab" data-bs-target="#nav-advanced"
|
||||||
|
type="button" role="tab" aria-controls="nav-advanced">{{ $t('inverteradmin.Advanced') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="tab-content" id="nav-tabContent">
|
<div class="tab-content" id="nav-tabContent">
|
||||||
@ -174,6 +176,13 @@
|
|||||||
<div :id="`inverter-customizer`" class="form-text" v-html="$t('inverteradmin.InverterHint')">
|
<div :id="`inverter-customizer`" class="form-text" v-html="$t('inverteradmin.InverterHint')">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-pane fade show" id="nav-advanced" role="tabpanel" aria-labelledby="nav-advanced-tab" tabindex="0">
|
||||||
|
<InputElement :label="$t('inverteradmin.ReachableThreshold')"
|
||||||
|
v-model="selectedInverterData.reachable_threshold"
|
||||||
|
type="number" min="1" max="100"
|
||||||
|
:tooltip="$t('inverteradmin.ReachableThresholdHint')" wide />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@ -247,6 +256,7 @@ declare interface Inverter {
|
|||||||
poll_enable_night: boolean;
|
poll_enable_night: boolean;
|
||||||
command_enable: boolean;
|
command_enable: boolean;
|
||||||
command_enable_night: boolean;
|
command_enable_night: boolean;
|
||||||
|
reachable_threshold: number;
|
||||||
channel: Array<Channel>;
|
channel: Array<Channel>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user