Merge remote-tracking branch 'tbnobody/OpenDTU/master' into development
This commit is contained in:
commit
3b62d5708a
@ -16,7 +16,7 @@
|
||||
"mdc": 23,
|
||||
"mdio": 18,
|
||||
"type": 0,
|
||||
"clk_mode": 3
|
||||
"clk_mode": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -35,6 +35,8 @@ public:
|
||||
static bool checkCredentials(AsyncWebServerRequest* request);
|
||||
static bool checkCredentialsReadonly(AsyncWebServerRequest* request);
|
||||
|
||||
static void sendTooManyRequests(AsyncWebServerRequest* request);
|
||||
|
||||
private:
|
||||
AsyncWebServer _server;
|
||||
AsyncEventSource _events;
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <Hoymiles.h>
|
||||
#include <map>
|
||||
|
||||
class WebApiPrometheusClass {
|
||||
public:
|
||||
@ -15,4 +16,28 @@ private:
|
||||
void addField(AsyncResponseStream* stream, String& serial, uint8_t idx, std::shared_ptr<InverterAbstract> inv, ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId, const char* channelName = NULL);
|
||||
|
||||
AsyncWebServer* _server;
|
||||
|
||||
enum {
|
||||
METRIC_TYPE_NONE = 0,
|
||||
METRIC_TYPE_GAUGE,
|
||||
METRIC_TYPE_COUNTER,
|
||||
};
|
||||
const char* _metricTypes[3] = { 0, "gauge", "counter" };
|
||||
|
||||
std::map<FieldId_t, uint8_t> _fieldMetricAssignment {
|
||||
{ FLD_UDC, METRIC_TYPE_GAUGE },
|
||||
{ FLD_IDC, METRIC_TYPE_GAUGE },
|
||||
{ FLD_PDC, METRIC_TYPE_GAUGE },
|
||||
{ FLD_YD, METRIC_TYPE_COUNTER },
|
||||
{ FLD_YT, METRIC_TYPE_COUNTER },
|
||||
{ FLD_UAC, METRIC_TYPE_GAUGE },
|
||||
{ FLD_IAC, METRIC_TYPE_GAUGE },
|
||||
{ FLD_PAC, METRIC_TYPE_GAUGE },
|
||||
{ FLD_F, METRIC_TYPE_GAUGE },
|
||||
{ FLD_T, METRIC_TYPE_GAUGE },
|
||||
{ FLD_PF, METRIC_TYPE_GAUGE },
|
||||
{ FLD_EFF, METRIC_TYPE_GAUGE },
|
||||
{ FLD_IRR, METRIC_TYPE_GAUGE },
|
||||
{ FLD_PRA, METRIC_TYPE_GAUGE }
|
||||
};
|
||||
};
|
||||
@ -34,7 +34,7 @@ String ResetReasonClass::get_reset_reason_verbose(uint8_t cpu_id)
|
||||
case 3:
|
||||
reason_str = F("Software reset digital core");
|
||||
break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
case 4:
|
||||
reason_str = F("Legacy watch dog reset digital core");
|
||||
break;
|
||||
@ -42,7 +42,7 @@ String ResetReasonClass::get_reset_reason_verbose(uint8_t cpu_id)
|
||||
case 5:
|
||||
reason_str = F("Deep Sleep reset digital core");
|
||||
break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
case 6:
|
||||
reason_str = F("Reset by SLC module, reset digital core");
|
||||
break;
|
||||
@ -68,9 +68,9 @@ String ResetReasonClass::get_reset_reason_verbose(uint8_t cpu_id)
|
||||
case 13:
|
||||
reason_str = F("RTC Watch dog Reset CPU");
|
||||
break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
case 14:
|
||||
reason_str = F("for APP CPU, reseted by PRO CPU");
|
||||
reason_str = F("for APP CPU, reset by PRO CPU");
|
||||
break;
|
||||
#endif
|
||||
case 15:
|
||||
@ -100,7 +100,7 @@ String ResetReasonClass::get_reset_reason_short(uint8_t cpu_id)
|
||||
case 3:
|
||||
reason_str = F("SW_RESET");
|
||||
break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
case 4:
|
||||
reason_str = F("OWDT_RESET");
|
||||
break;
|
||||
@ -108,7 +108,7 @@ String ResetReasonClass::get_reset_reason_short(uint8_t cpu_id)
|
||||
case 5:
|
||||
reason_str = F("DEEPSLEEP_RESET");
|
||||
break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
case 6:
|
||||
reason_str = F("SDIO_RESET");
|
||||
break;
|
||||
@ -134,7 +134,7 @@ String ResetReasonClass::get_reset_reason_short(uint8_t cpu_id)
|
||||
case 13:
|
||||
reason_str = F("RTCWDT_CPU_RESET");
|
||||
break;
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
case 14:
|
||||
reason_str = F("EXT_CPU_RESET");
|
||||
break;
|
||||
@ -152,4 +152,4 @@ String ResetReasonClass::get_reset_reason_short(uint8_t cpu_id)
|
||||
return reason_str;
|
||||
}
|
||||
|
||||
ResetReasonClass ResetReason;
|
||||
ResetReasonClass ResetReason;
|
||||
|
||||
@ -98,4 +98,11 @@ bool WebApiClass::checkCredentialsReadonly(AsyncWebServerRequest* request)
|
||||
}
|
||||
}
|
||||
|
||||
void WebApiClass::sendTooManyRequests(AsyncWebServerRequest* request)
|
||||
{
|
||||
auto response = request->beginResponse(429, "text/plain", "Too Many Requests");
|
||||
response->addHeader("Retry-After", "60");
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
WebApiClass WebApi;
|
||||
@ -5,7 +5,9 @@
|
||||
*/
|
||||
#include "WebApi_prometheus.h"
|
||||
#include "Configuration.h"
|
||||
#include "MessageOutput.h"
|
||||
#include "NetworkSettings.h"
|
||||
#include "WebApi.h"
|
||||
#include <Hoymiles.h>
|
||||
#include "MessageOutput.h"
|
||||
|
||||
@ -23,10 +25,10 @@ void WebApiPrometheusClass::loop()
|
||||
}
|
||||
|
||||
void WebApiPrometheusClass::onPrometheusMetricsGet(AsyncWebServerRequest* request)
|
||||
{
|
||||
{
|
||||
try {
|
||||
auto stream = request->beginResponseStream("text/plain; charset=utf-8", 40960);
|
||||
|
||||
|
||||
stream->print(F("# HELP opendtu_build Build info\n"));
|
||||
stream->print(F("# TYPE opendtu_build gauge\n"));
|
||||
stream->printf("opendtu_build{name=\"%s\",id=\"%s\",version=\"%d.%d.%d\"} 1\n",
|
||||
@ -64,39 +66,39 @@ void WebApiPrometheusClass::onPrometheusMetricsGet(AsyncWebServerRequest* reques
|
||||
stream->printf("opendtu_last_update{serial=\"%s\",unit=\"%d\",name=\"%s\"} %d\n",
|
||||
serial.c_str(), i, name, inv->Statistics()->getLastUpdate() / 1000);
|
||||
|
||||
// Loop all channels
|
||||
for (auto& t : inv->Statistics()->getChannelTypes()) {
|
||||
for (auto& c : inv->Statistics()->getChannelsByType(t)) {
|
||||
addField(stream, serial, i, inv, t, c, FLD_PAC);
|
||||
addField(stream, serial, i, inv, t, c, FLD_UAC);
|
||||
addField(stream, serial, i, inv, t, c, FLD_IAC);
|
||||
if (t == TYPE_AC) {
|
||||
addField(stream, serial, i, inv, t, c, FLD_PDC, "PowerDC");
|
||||
} else {
|
||||
addField(stream, serial, i, inv, t, c, FLD_PDC);
|
||||
// Loop all channels if Statistics have been updated at least once since DTU boot
|
||||
if (inv->Statistics()->getLastUpdate() > 0) {
|
||||
for (auto& t : inv->Statistics()->getChannelTypes()) {
|
||||
for (auto& c : inv->Statistics()->getChannelsByType(t)) {
|
||||
addField(stream, serial, i, inv, t, c, FLD_PAC);
|
||||
addField(stream, serial, i, inv, t, c, FLD_UAC);
|
||||
addField(stream, serial, i, inv, t, c, FLD_IAC);
|
||||
if (t == TYPE_AC) {
|
||||
addField(stream, serial, i, inv, t, c, FLD_PDC, "PowerDC");
|
||||
} else {
|
||||
addField(stream, serial, i, inv, t, c, FLD_PDC);
|
||||
}
|
||||
addField(stream, serial, i, inv, t, c, FLD_UDC);
|
||||
addField(stream, serial, i, inv, t, c, FLD_IDC);
|
||||
addField(stream, serial, i, inv, t, c, FLD_YD);
|
||||
addField(stream, serial, i, inv, t, c, FLD_YT);
|
||||
addField(stream, serial, i, inv, t, c, FLD_F);
|
||||
addField(stream, serial, i, inv, t, c, FLD_T);
|
||||
addField(stream, serial, i, inv, t, c, FLD_PF);
|
||||
addField(stream, serial, i, inv, t, c, FLD_PRA);
|
||||
addField(stream, serial, i, inv, t, c, FLD_EFF);
|
||||
addField(stream, serial, i, inv, t, c, FLD_IRR);
|
||||
}
|
||||
addField(stream, serial, i, inv, t, c, FLD_UDC);
|
||||
addField(stream, serial, i, inv, t, c, FLD_IDC);
|
||||
addField(stream, serial, i, inv, t, c, FLD_YD);
|
||||
addField(stream, serial, i, inv, t, c, FLD_YT);
|
||||
addField(stream, serial, i, inv, t, c, FLD_F);
|
||||
addField(stream, serial, i, inv, t, c, FLD_T);
|
||||
addField(stream, serial, i, inv, t, c, FLD_PF);
|
||||
addField(stream, serial, i, inv, t, c, FLD_PRA);
|
||||
addField(stream, serial, i, inv, t, c, FLD_EFF);
|
||||
addField(stream, serial, i, inv, t, c, FLD_IRR);
|
||||
}
|
||||
}
|
||||
}
|
||||
stream->addHeader(F("Cache-Control"), F("no-cache"));
|
||||
request->send(stream);
|
||||
}
|
||||
catch (std::bad_alloc& bad_alloc) {
|
||||
|
||||
} catch (std::bad_alloc& bad_alloc) {
|
||||
MessageOutput.printf("Call to /api/prometheus/metrics temporarely out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
||||
|
||||
auto response = request->beginResponse(429, "text/plain", "Too Many Requests");
|
||||
response->addHeader("Retry-After", "60");
|
||||
request->send(response);
|
||||
|
||||
WebApi.sendTooManyRequests(request);
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,7 +108,7 @@ void WebApiPrometheusClass::addField(AsyncResponseStream* stream, String& serial
|
||||
const char* chanName = (channelName == NULL) ? inv->Statistics()->getChannelFieldName(type, channel, fieldId) : channelName;
|
||||
if (idx == 0 && type == TYPE_AC && channel == 0) {
|
||||
stream->printf("# HELP opendtu_%s in %s\n", chanName, inv->Statistics()->getChannelFieldUnit(type, channel, fieldId));
|
||||
stream->printf("# TYPE opendtu_%s gauge\n", chanName);
|
||||
stream->printf("# TYPE opendtu_%s %s\n", chanName, _metricTypes[_fieldMetricAssignment[fieldId]]);
|
||||
}
|
||||
stream->printf("opendtu_%s{serial=\"%s\",unit=\"%d\",name=\"%s\",type=\"%s\",channel=\"%d\"} %f\n",
|
||||
chanName,
|
||||
|
||||
@ -59,6 +59,7 @@ void WebApiWsLiveClass::loop()
|
||||
|
||||
// Update on every inverter change or at least after 10 seconds
|
||||
if (millis() - _lastWsPublish > (10 * 1000) || (maxTimeStamp != _newestInverterTimestamp)) {
|
||||
|
||||
try {
|
||||
DynamicJsonDocument root(40960);
|
||||
JsonVariant var = root;
|
||||
@ -77,11 +78,11 @@ void WebApiWsLiveClass::loop()
|
||||
_ws.textAll(buffer);
|
||||
}
|
||||
|
||||
_lastWsPublish = millis();
|
||||
}
|
||||
catch (std::bad_alloc& bad_alloc) {
|
||||
} catch (std::bad_alloc& bad_alloc) {
|
||||
MessageOutput.printf("Call to /api/livedata/status temporarely out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
||||
}
|
||||
|
||||
_lastWsPublish = millis();
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,11 +225,18 @@ void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 40960U);
|
||||
JsonVariant root = response->getRoot();
|
||||
try {
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 40960U);
|
||||
JsonVariant root = response->getRoot();
|
||||
|
||||
generateJsonResponse(root);
|
||||
generateJsonResponse(root);
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
} catch (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);
|
||||
}
|
||||
}
|
||||
@ -55,6 +55,7 @@ void WebApiWsVedirectLiveClass::loop()
|
||||
|
||||
// Update on ve.direct change or at least after 10 seconds
|
||||
if (millis() - _lastWsPublish > (10 * 1000) || (maxTimeStamp != _newestVedirectTimestamp)) {
|
||||
|
||||
try {
|
||||
DynamicJsonDocument root(1024);
|
||||
JsonVariant var = root;
|
||||
@ -73,11 +74,11 @@ void WebApiWsVedirectLiveClass::loop()
|
||||
_ws.textAll(buffer);
|
||||
}
|
||||
|
||||
_lastWsPublish = millis();
|
||||
}
|
||||
catch (std::bad_alloc& bad_alloc) {
|
||||
} catch (std::bad_alloc& bad_alloc) {
|
||||
MessageOutput.printf("Call to /api/vedirectlivedata/status temporarely out of resources. Reason: \"%s\".\r\n", bad_alloc.what());
|
||||
}
|
||||
|
||||
_lastWsPublish = millis();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,18 @@
|
||||
</BootstrapAlert>
|
||||
<table v-if="devInfoList.valid_data" class="table table-hover">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ $t('devinfo.Serial') }}</td>
|
||||
<td>{{ devInfoList.serial }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('devinfo.ProdYear') }}</td>
|
||||
<td>{{ productionYear() }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('devinfo.ProdWeek') }}</td>
|
||||
<td>{{ productionWeek() }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('devinfo.Model') }}</td>
|
||||
<td v-if="devInfoList.hw_model_name != ''">{{ devInfoList.hw_model_name }}</td>
|
||||
@ -61,6 +73,16 @@ export default defineComponent({
|
||||
const version_patch = Math.floor((value - version_major * 10000 - version_minor * 100));
|
||||
return version_major + "." + version_minor + "." + version_patch;
|
||||
};
|
||||
},
|
||||
productionYear() {
|
||||
return() => {
|
||||
return ((parseInt(this.devInfoList.serial.toString(), 16) >> (7 * 4)) & 0xF) + 2014;
|
||||
}
|
||||
},
|
||||
productionWeek() {
|
||||
return() => {
|
||||
return ((parseInt(this.devInfoList.serial.toString(), 16) >> (5 * 4)) & 0xFF).toString(16);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -159,6 +159,9 @@
|
||||
"NoInfo": "Keine Informationen verfügbar",
|
||||
"NoInfoLong": "Bisher wurden noch keine gültigen Daten vom Wechselrichter empfangen. Versuche es weiter...",
|
||||
"UnknownModel": "Unbekanntes Modell! Bitte melden Sie die \"Hardware Teilenummer\" und das Modell (z.B. HM-350) <a href=\"https://github.com/tbnobody/OpenDTU/issues\" target=\"_blank\">hier</a> als Problem.",
|
||||
"Serial": "Seriennummer",
|
||||
"ProdYear": "Produktionsjahr",
|
||||
"ProdWeek": "Produktionswoche",
|
||||
"Model": "Modell",
|
||||
"DetectedMaxPower": "Ermittelte max. Leistung",
|
||||
"BootloaderVersion": "Bootloader-Version",
|
||||
|
||||
@ -159,6 +159,9 @@
|
||||
"NoInfo": "No Information available",
|
||||
"NoInfoLong": "Did not receive any valid data from the inverter till now. Still trying...",
|
||||
"UnknownModel": "Unknown model! Please report the \"Hardware Part Number\" and model (e.g. HM-350) as an issue <a href=\"https://github.com/tbnobody/OpenDTU/issues\" target=\"_blank\">here</a>.",
|
||||
"Serial": "Serial",
|
||||
"ProdYear": "Production Year",
|
||||
"ProdWeek": "Production Week",
|
||||
"Model": "Model",
|
||||
"DetectedMaxPower": "Detected max. Power",
|
||||
"BootloaderVersion": "Bootloader Version",
|
||||
|
||||
@ -2,14 +2,14 @@
|
||||
"menu": {
|
||||
"LiveView": "Direct",
|
||||
"Settings": "Paramètres",
|
||||
"NetworkSettings": "Paramètres réseau",
|
||||
"NTPSettings": "Paramètres NTP",
|
||||
"MQTTSettings": "Paramètres MQTT",
|
||||
"InverterSettings": "Paramètres des onduleurs",
|
||||
"SecuritySettings": "Paramètres de sécurité",
|
||||
"DTUSettings": "Paramètres DTU",
|
||||
"DeviceManager": "Gestionnaire de périphériques",
|
||||
"VedirectSettings": "Paramètres Ve.direct",
|
||||
"NetworkSettings": "Réseau",
|
||||
"NTPSettings": "Heure locale",
|
||||
"MQTTSettings": "MQTT",
|
||||
"InverterSettings": "Onduleurs",
|
||||
"SecuritySettings": "Sécurité",
|
||||
"DTUSettings": "DTU",
|
||||
"DeviceManager": "Périphériques",
|
||||
"VedirectSettings": "Ve.direct",
|
||||
"ConfigManagement": "Gestion de la configuration",
|
||||
"FirmwareUpgrade": "Mise à jour du firmware",
|
||||
"DeviceReboot": "Redémarrage de l'appareil",
|
||||
@ -158,6 +158,9 @@
|
||||
"NoInfo": "Aucune information disponible",
|
||||
"NoInfoLong": "N'a pas reçu de données valides de l'onduleur jusqu'à présent. J'essaie toujours...",
|
||||
"UnknownModel": "Modèle inconnu ! Veuillez signaler le \"Numéro d'article matériel\" et le modèle (par exemple, HM-350) comme un problème <a href=\"https://github.com/tbnobody/OpenDTU/issues\" target=\"_blank\">ici</a>.",
|
||||
"Serial": "Serial",
|
||||
"ProdYear": "Production Year",
|
||||
"ProdWeek": "Production Week",
|
||||
"Model": "Modèle",
|
||||
"DetectedMaxPower": "Puissance maximale détectée",
|
||||
"BootloaderVersion": "Version du bootloader",
|
||||
@ -372,7 +375,7 @@
|
||||
"TimeServerHint": "La valeur par défaut convient tant que OpenDTU a un accès direct à Internet.",
|
||||
"Timezone": "Fuseau horaire",
|
||||
"TimezoneConfig": "Configuration du fuseau horaire",
|
||||
"LocationConfiguration": "Location Configuration",
|
||||
"LocationConfiguration": "Géolocalisation",
|
||||
"Longitude": "Longitude",
|
||||
"Latitude": "Latitude",
|
||||
"Save": "@:dtuadmin.Save",
|
||||
@ -450,10 +453,10 @@
|
||||
"Add": "Ajouter",
|
||||
"AddHint": " <b>Astuce :</b> Vous pouvez définir des paramètres supplémentaires après avoir créé l'onduleur. Utilisez l'icône du stylo dans la liste des onduleurs.",
|
||||
"InverterList": "Liste des onduleurs",
|
||||
"Status": "Status",
|
||||
"Send": "Send",
|
||||
"Receive": "Receive",
|
||||
"StatusHint": "<b>Astuce :</b> The inverter is power by it's DC input. If there is no sun, the inverter is off. Requests can still be sent.",
|
||||
"Status": "État",
|
||||
"Send": "Envoyer",
|
||||
"Receive": "Recevoir",
|
||||
"StatusHint": "<b>Astuce :</b> L'onduleur est alimenté par son entrée courant continu. S'il n'y a pas de soleil, l'onduleur est éteint, mais les requêtes peuvent toujours être envoyées.",
|
||||
"Type": "Type",
|
||||
"Action": "Action",
|
||||
"DeleteInverter": "Supprimer l'onduleur",
|
||||
@ -462,16 +465,16 @@
|
||||
"InverterName": "Nom de l'onduleur :",
|
||||
"InverterNameHint": "Ici, vous pouvez spécifier un nom personnalisé pour votre onduleur.",
|
||||
"InverterStatus": "Receive / Send",
|
||||
"PollEnable": "Poll inverter data",
|
||||
"PollEnableNight": "Poll inverter data at night",
|
||||
"CommandEnable": "Send commands",
|
||||
"CommandEnableNight": "Send commands at night",
|
||||
"PollEnable": "Interroger les données de l'onduleur",
|
||||
"PollEnableNight": "Interroger les données de l'onduleur la nuit",
|
||||
"CommandEnable": "Envoyer des commandes",
|
||||
"CommandEnableNight": "Envoyer des commandes la nuit",
|
||||
"StringName": "Nom de la ligne {num}:",
|
||||
"StringNameHint": "Ici, vous pouvez spécifier un nom personnalisé pour le port respectif de votre onduleur.",
|
||||
"StringMaxPower": "Puissance maximale de la ligne {num}:",
|
||||
"StringMaxPowerHint": "Entrez la puissance maximale des panneaux solaires connectés.",
|
||||
"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.",
|
||||
"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é.",
|
||||
"InverterHint": "*) Entrez le W<sub>p</sub> du canal pour calculer l'irradiation.",
|
||||
"Cancel": "@:maintenancereboot.Cancel",
|
||||
"Save": "@:dtuadmin.Save",
|
||||
@ -483,8 +486,8 @@
|
||||
"BackupHeader": "Sauvegarder le fichier de configuration",
|
||||
"BackupConfig": "Fichier de configuration",
|
||||
"Backup": "Sauvegarder",
|
||||
"Restore": "Restore",
|
||||
"NoFileSelected": "No file selected",
|
||||
"Restore": "Restaurer",
|
||||
"NoFileSelected": "Aucun fichier sélectionné",
|
||||
"RestoreHeader": "Restaurer le fichier de configuration",
|
||||
"Back": "Retour",
|
||||
"UploadSuccess": "Succès du téléversement",
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
export interface DevInfoStatus {
|
||||
serial: number;
|
||||
valid_data: boolean;
|
||||
fw_bootloader_version: number;
|
||||
fw_build_version: number;
|
||||
|
||||
@ -543,6 +543,7 @@ export default defineComponent({
|
||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||
.then((data) => {
|
||||
this.devInfoList = data[serial][0];
|
||||
this.devInfoList.serial = serial;
|
||||
this.devInfoLoading = false;
|
||||
});
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user