Merge remote-tracking branch 'tbnobody/OpenDTU/master'
This commit is contained in:
commit
b3295f5f33
@ -24,6 +24,9 @@ serial will be replaced with the serial number of the inverter.
|
|||||||
| [serial]/device/fwbuilddatetime | R | Build date / time of inverter firmware | |
|
| [serial]/device/fwbuilddatetime | R | Build date / time of inverter firmware | |
|
||||||
| [serial]/device/hwpartnumber | R | Hardware part number of the inverter | |
|
| [serial]/device/hwpartnumber | R | Hardware part number of the inverter | |
|
||||||
| [serial]/device/hwversion | R | Hardware version of the inverter | |
|
| [serial]/device/hwversion | R | Hardware version of the inverter | |
|
||||||
|
| [serial]/status/reachable | R | Indicates whether the inverter is reachable | 0 or 1 |
|
||||||
|
| [serial]/status/producing | R | Indicates whether the inverter is producing AC power | 0 or 1 |
|
||||||
|
| [serial]/status/last_update | R | Unix timestamp of last inverter statistics udpate | seconds since JAN 01 1970 (UTC) |
|
||||||
|
|
||||||
### AC channel / global specific topics
|
### AC channel / global specific topics
|
||||||
|
|
||||||
@ -62,8 +65,6 @@ cmd topics are used to set values. Status topics are updated from values set in
|
|||||||
| ----------------------------------------- | ----- | ---------------------------------------------------- | -------------------------- |
|
| ----------------------------------------- | ----- | ---------------------------------------------------- | -------------------------- |
|
||||||
| [serial]/status/limit_relative | R | Current applied production limit of the inverter | % of total possible output |
|
| [serial]/status/limit_relative | R | Current applied production limit of the inverter | % of total possible output |
|
||||||
| [serial]/status/limit_absolute | R | Current applied production limit of the inverter | Watt (W) |
|
| [serial]/status/limit_absolute | R | Current applied production limit of the inverter | Watt (W) |
|
||||||
| [serial]/status/reachable | R | Indicates whether the inverter is reachable | 0 or 1 |
|
|
||||||
| [serial]/status/producing | R | Indicates whether the inverter is producing AC power | 0 or 1 |
|
|
||||||
| [serial]/cmd/limit_persistent_relative | W | Set the inverter limit as a percentage of total production capability. The value will survive the night without power. The updated value will show up in the web GUI and limit_relative topic immediatly. | % |
|
| [serial]/cmd/limit_persistent_relative | W | Set the inverter limit as a percentage of total production capability. The value will survive the night without power. The updated value will show up in the web GUI and limit_relative topic immediatly. | % |
|
||||||
| [serial]/cmd/limit_persistent_absolute | W | Set the inverter limit as a absolute value. The value will survive the night without power. The updated value will show up in the web GUI and limit_relative topic after around 4 minutes. | Watt (W) |
|
| [serial]/cmd/limit_persistent_absolute | W | Set the inverter limit as a absolute value. The value will survive the night without power. The updated value will show up in the web GUI and limit_relative topic after around 4 minutes. | Watt (W) |
|
||||||
| [serial]/cmd/limit_nonpersistent_relative | W | Set the inverter limit as a percentage of total production capability. The value will reset to the last persistent value at night without power. The updated value will show up in the web GUI and limit_relative topic immediatly. | % |
|
| [serial]/cmd/limit_nonpersistent_relative | W | Set the inverter limit as a percentage of total production capability. The value will reset to the last persistent value at night without power. The updated value will show up in the web GUI and limit_relative topic immediatly. | % |
|
||||||
|
|||||||
@ -44,7 +44,7 @@ const byteAssign_fieldDeviceClass_t deviceFieldAssignment[] = {
|
|||||||
{ FLD_PAC, DEVICE_CLS_PWR, STATE_CLS_MEASUREMENT },
|
{ FLD_PAC, DEVICE_CLS_PWR, STATE_CLS_MEASUREMENT },
|
||||||
{ FLD_F, DEVICE_CLS_FREQ, STATE_CLS_MEASUREMENT },
|
{ FLD_F, DEVICE_CLS_FREQ, STATE_CLS_MEASUREMENT },
|
||||||
{ FLD_T, DEVICE_CLS_TEMP, STATE_CLS_MEASUREMENT },
|
{ FLD_T, DEVICE_CLS_TEMP, STATE_CLS_MEASUREMENT },
|
||||||
{ FLD_PCT, DEVICE_CLS_POWER_FACTOR, STATE_CLS_MEASUREMENT },
|
{ FLD_PF, DEVICE_CLS_POWER_FACTOR, STATE_CLS_MEASUREMENT },
|
||||||
{ FLD_EFF, DEVICE_CLS_NONE, STATE_CLS_NONE },
|
{ FLD_EFF, DEVICE_CLS_NONE, STATE_CLS_NONE },
|
||||||
{ FLD_IRR, DEVICE_CLS_NONE, STATE_CLS_NONE },
|
{ FLD_IRR, DEVICE_CLS_NONE, STATE_CLS_NONE },
|
||||||
{ FLD_PRA, DEVICE_CLS_REACTIVE_POWER, STATE_CLS_MEASUREMENT }
|
{ FLD_PRA, DEVICE_CLS_REACTIVE_POWER, STATE_CLS_MEASUREMENT }
|
||||||
|
|||||||
@ -30,7 +30,7 @@ private:
|
|||||||
FLD_PAC,
|
FLD_PAC,
|
||||||
FLD_F,
|
FLD_F,
|
||||||
FLD_T,
|
FLD_T,
|
||||||
FLD_PCT,
|
FLD_PF,
|
||||||
FLD_EFF,
|
FLD_EFF,
|
||||||
FLD_IRR,
|
FLD_IRR,
|
||||||
FLD_PRA
|
FLD_PRA
|
||||||
|
|||||||
@ -13,7 +13,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void generateJsonResponse(JsonVariant& root);
|
void generateJsonResponse(JsonVariant& root);
|
||||||
void addField(JsonVariant& root, uint8_t idx, std::shared_ptr<InverterAbstract> inv, uint8_t channel, uint8_t fieldId, String topic = "");
|
void addField(JsonObject& root, uint8_t idx, std::shared_ptr<InverterAbstract> inv, uint8_t channel, uint8_t fieldId, String topic = "");
|
||||||
|
void addTotalField(JsonObject& root, String name, float value, String unit, uint8_t digits);
|
||||||
void onLivedataStatus(AsyncWebServerRequest* request);
|
void onLivedataStatus(AsyncWebServerRequest* request);
|
||||||
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
void onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len);
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
* CommandAbstract
|
* CommandAbstract
|
||||||
* DevControlCommand
|
* DevControlCommand
|
||||||
* ActivePowerControlCommand
|
* ActivePowerControlCommand
|
||||||
|
* PowerControlCommand
|
||||||
* MultiDataCommand
|
* MultiDataCommand
|
||||||
* AlarmDataCommand
|
* AlarmDataCommand
|
||||||
* DevInfoAllCommand
|
* DevInfoAllCommand
|
||||||
|
|||||||
@ -24,9 +24,9 @@ private:
|
|||||||
{ FLD_PAC, UNIT_W, CH0, 18, 2, 10, false },
|
{ FLD_PAC, UNIT_W, CH0, 18, 2, 10, false },
|
||||||
{ FLD_PRA, UNIT_VA, CH0, 20, 2, 10, false },
|
{ FLD_PRA, UNIT_VA, CH0, 20, 2, 10, false },
|
||||||
{ FLD_F, UNIT_HZ, CH0, 16, 2, 100, false },
|
{ FLD_F, UNIT_HZ, CH0, 16, 2, 100, false },
|
||||||
{ FLD_PCT, UNIT_PCT, CH0, 24, 2, 10, false },
|
{ FLD_PF, UNIT_NONE, CH0, 24, 2, 1000, false },
|
||||||
{ FLD_T, UNIT_C, CH0, 26, 2, 10, true },
|
{ FLD_T, UNIT_C, CH0, 26, 2, 10, true },
|
||||||
{ FLD_EVT_LOG, UNIT_CNT, CH0, 28, 2, 1, false },
|
{ FLD_EVT_LOG, UNIT_NONE, CH0, 28, 2, 1, false },
|
||||||
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC, false },
|
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC, false },
|
||||||
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC, false },
|
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC, false },
|
||||||
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC, false },
|
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC, false },
|
||||||
|
|||||||
@ -31,9 +31,9 @@ private:
|
|||||||
{ FLD_PAC, UNIT_W, CH0, 30, 2, 10, false },
|
{ FLD_PAC, UNIT_W, CH0, 30, 2, 10, false },
|
||||||
{ FLD_PRA, UNIT_VA, CH0, 32, 2, 10, false },
|
{ FLD_PRA, UNIT_VA, CH0, 32, 2, 10, false },
|
||||||
{ FLD_F, UNIT_HZ, CH0, 28, 2, 100, false },
|
{ FLD_F, UNIT_HZ, CH0, 28, 2, 100, false },
|
||||||
{ FLD_PCT, UNIT_PCT, CH0, 36, 2, 10, false },
|
{ FLD_PF, UNIT_NONE, CH0, 36, 2, 1000, false },
|
||||||
{ FLD_T, UNIT_C, CH0, 38, 2, 10, true },
|
{ FLD_T, UNIT_C, CH0, 38, 2, 10, true },
|
||||||
{ FLD_EVT_LOG, UNIT_CNT, CH0, 40, 2, 1, false },
|
{ FLD_EVT_LOG, UNIT_NONE, CH0, 40, 2, 1, false },
|
||||||
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC, false },
|
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC, false },
|
||||||
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC, false },
|
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC, false },
|
||||||
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC, false },
|
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC, false },
|
||||||
|
|||||||
@ -45,9 +45,9 @@ private:
|
|||||||
{ FLD_PAC, UNIT_W, CH0, 50, 2, 10, false },
|
{ FLD_PAC, UNIT_W, CH0, 50, 2, 10, false },
|
||||||
{ FLD_PRA, UNIT_VA, CH0, 52, 2, 10, false },
|
{ FLD_PRA, UNIT_VA, CH0, 52, 2, 10, false },
|
||||||
{ FLD_F, UNIT_HZ, CH0, 48, 2, 100, false },
|
{ FLD_F, UNIT_HZ, CH0, 48, 2, 100, false },
|
||||||
{ FLD_PCT, UNIT_PCT, CH0, 56, 2, 10, false },
|
{ FLD_PF, UNIT_NONE, CH0, 56, 2, 1000, false },
|
||||||
{ FLD_T, UNIT_C, CH0, 58, 2, 10, true },
|
{ FLD_T, UNIT_C, CH0, 58, 2, 10, true },
|
||||||
{ FLD_EVT_LOG, UNIT_CNT, CH0, 60, 2, 1, false },
|
{ FLD_EVT_LOG, UNIT_NONE, CH0, 60, 2, 1, false },
|
||||||
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC, false },
|
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC, false },
|
||||||
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC, false },
|
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC, false },
|
||||||
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC, false },
|
{ FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC, false },
|
||||||
|
|||||||
@ -120,6 +120,25 @@ const char* StatisticsParser::getChannelFieldName(uint8_t channel, uint8_t field
|
|||||||
return fields[b[pos].fieldId];
|
return fields[b[pos].fieldId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t StatisticsParser::getChannelFieldDigits(uint8_t channel, uint8_t fieldId)
|
||||||
|
{
|
||||||
|
uint8_t pos = getAssignIdxByChannelField(channel, fieldId);
|
||||||
|
const byteAssign_t* b = _byteAssignment;
|
||||||
|
|
||||||
|
switch (b[pos].div) {
|
||||||
|
case 1:
|
||||||
|
return 0;
|
||||||
|
case 10:
|
||||||
|
return 1;
|
||||||
|
case 100:
|
||||||
|
return 2;
|
||||||
|
case 1000:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t StatisticsParser::getChannelCount()
|
uint8_t StatisticsParser::getChannelCount()
|
||||||
{
|
{
|
||||||
const byteAssign_t* b = _byteAssignment;
|
const byteAssign_t* b = _byteAssignment;
|
||||||
|
|||||||
@ -16,7 +16,7 @@ enum {
|
|||||||
UNIT_C,
|
UNIT_C,
|
||||||
UNIT_PCT,
|
UNIT_PCT,
|
||||||
UNIT_VA,
|
UNIT_VA,
|
||||||
UNIT_CNT
|
UNIT_NONE
|
||||||
};
|
};
|
||||||
const char* const units[] = { "V", "A", "W", "Wh", "kWh", "Hz", "°C", "%", "var", "" };
|
const char* const units[] = { "V", "A", "W", "Wh", "kWh", "Hz", "°C", "%", "var", "" };
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ enum {
|
|||||||
FLD_PAC,
|
FLD_PAC,
|
||||||
FLD_F,
|
FLD_F,
|
||||||
FLD_T,
|
FLD_T,
|
||||||
FLD_PCT,
|
FLD_PF,
|
||||||
FLD_EFF,
|
FLD_EFF,
|
||||||
FLD_IRR,
|
FLD_IRR,
|
||||||
FLD_PRA,
|
FLD_PRA,
|
||||||
@ -83,6 +83,7 @@ public:
|
|||||||
bool hasChannelFieldValue(uint8_t channel, uint8_t fieldId);
|
bool hasChannelFieldValue(uint8_t channel, uint8_t fieldId);
|
||||||
const char* getChannelFieldUnit(uint8_t channel, uint8_t fieldId);
|
const char* getChannelFieldUnit(uint8_t channel, uint8_t fieldId);
|
||||||
const char* getChannelFieldName(uint8_t channel, uint8_t fieldId);
|
const char* getChannelFieldName(uint8_t channel, uint8_t fieldId);
|
||||||
|
uint8_t getChannelFieldDigits(uint8_t channel, uint8_t fieldId);
|
||||||
|
|
||||||
uint8_t getChannelCount();
|
uint8_t getChannelCount();
|
||||||
|
|
||||||
|
|||||||
@ -71,6 +71,12 @@ void MqttPublishingClass::loop()
|
|||||||
MqttSettings.publish(subtopic + "/status/reachable", String(inv->isReachable()));
|
MqttSettings.publish(subtopic + "/status/reachable", String(inv->isReachable()));
|
||||||
MqttSettings.publish(subtopic + "/status/producing", String(inv->isProducing()));
|
MqttSettings.publish(subtopic + "/status/producing", String(inv->isProducing()));
|
||||||
|
|
||||||
|
if (inv->Statistics()->getLastUpdate() > 0) {
|
||||||
|
MqttSettings.publish(subtopic + "/status/last_update", String(std::time(0) - (millis() - inv->Statistics()->getLastUpdate()) / 1000));
|
||||||
|
} else {
|
||||||
|
MqttSettings.publish(subtopic + "/status/last_update", String(0));
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t lastUpdate = inv->Statistics()->getLastUpdate();
|
uint32_t lastUpdate = inv->Statistics()->getLastUpdate();
|
||||||
if (lastUpdate > 0 && lastUpdate != _lastPublishStats[i]) {
|
if (lastUpdate > 0 && lastUpdate != _lastPublishStats[i]) {
|
||||||
_lastPublishStats[i] = lastUpdate;
|
_lastPublishStats[i] = lastUpdate;
|
||||||
|
|||||||
@ -73,57 +73,78 @@ void WebApiWsLiveClass::loop()
|
|||||||
|
|
||||||
void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
|
void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
|
||||||
{
|
{
|
||||||
|
JsonArray invArray = root.createNestedArray("inverters");
|
||||||
|
|
||||||
|
float totalPower = 0;
|
||||||
|
float totalYieldDay = 0;
|
||||||
|
float totalYieldTotal = 0;
|
||||||
|
|
||||||
// Loop all inverters
|
// Loop all inverters
|
||||||
for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) {
|
for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) {
|
||||||
auto inv = Hoymiles.getInverterByPos(i);
|
auto inv = Hoymiles.getInverterByPos(i);
|
||||||
|
if (inv == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
root[i][F("serial")] = inv->serialString();
|
JsonObject invObject = invArray.createNestedObject();
|
||||||
root[i][F("name")] = inv->name();
|
|
||||||
root[i][F("data_age")] = (millis() - inv->Statistics()->getLastUpdate()) / 1000;
|
invObject[F("serial")] = inv->serialString();
|
||||||
root[i][F("reachable")] = inv->isReachable();
|
invObject[F("name")] = inv->name();
|
||||||
root[i][F("producing")] = inv->isProducing();
|
invObject[F("data_age")] = (millis() - inv->Statistics()->getLastUpdate()) / 1000;
|
||||||
root[i][F("limit_relative")] = inv->SystemConfigPara()->getLimitPercent();
|
invObject[F("reachable")] = inv->isReachable();
|
||||||
|
invObject[F("producing")] = inv->isProducing();
|
||||||
|
invObject[F("limit_relative")] = inv->SystemConfigPara()->getLimitPercent();
|
||||||
if (inv->DevInfo()->getMaxPower() > 0) {
|
if (inv->DevInfo()->getMaxPower() > 0) {
|
||||||
root[i][F("limit_absolute")] = inv->SystemConfigPara()->getLimitPercent() * inv->DevInfo()->getMaxPower() / 100.0;
|
invObject[F("limit_absolute")] = inv->SystemConfigPara()->getLimitPercent() * inv->DevInfo()->getMaxPower() / 100.0;
|
||||||
} else {
|
} else {
|
||||||
root[i][F("limit_absolute")] = -1;
|
invObject[F("limit_absolute")] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop all channels
|
// Loop all channels
|
||||||
for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) {
|
for (uint8_t c = 0; c <= inv->Statistics()->getChannelCount(); c++) {
|
||||||
addField(root, i, inv, c, FLD_PAC);
|
addField(invObject, i, inv, c, FLD_PAC);
|
||||||
addField(root, i, inv, c, FLD_UAC);
|
addField(invObject, i, inv, c, FLD_UAC);
|
||||||
addField(root, i, inv, c, FLD_IAC);
|
addField(invObject, i, inv, c, FLD_IAC);
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
addField(root, i, inv, c, FLD_PDC, F("Power DC"));
|
addField(invObject, i, inv, c, FLD_PDC, F("Power DC"));
|
||||||
} else {
|
} else {
|
||||||
addField(root, i, inv, c, FLD_PDC);
|
addField(invObject, i, inv, c, FLD_PDC);
|
||||||
}
|
}
|
||||||
addField(root, i, inv, c, FLD_UDC);
|
addField(invObject, i, inv, c, FLD_UDC);
|
||||||
addField(root, i, inv, c, FLD_IDC);
|
addField(invObject, i, inv, c, FLD_IDC);
|
||||||
addField(root, i, inv, c, FLD_YD);
|
addField(invObject, i, inv, c, FLD_YD);
|
||||||
addField(root, i, inv, c, FLD_YT);
|
addField(invObject, i, inv, c, FLD_YT);
|
||||||
addField(root, i, inv, c, FLD_F);
|
addField(invObject, i, inv, c, FLD_F);
|
||||||
addField(root, i, inv, c, FLD_T);
|
addField(invObject, i, inv, c, FLD_T);
|
||||||
addField(root, i, inv, c, FLD_PCT);
|
addField(invObject, i, inv, c, FLD_PF);
|
||||||
addField(root, i, inv, c, FLD_PRA);
|
addField(invObject, i, inv, c, FLD_PRA);
|
||||||
addField(root, i, inv, c, FLD_EFF);
|
addField(invObject, i, inv, c, FLD_EFF);
|
||||||
addField(root, i, inv, c, FLD_IRR);
|
addField(invObject, i, inv, c, FLD_IRR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inv->Statistics()->hasChannelFieldValue(CH0, FLD_EVT_LOG)) {
|
if (inv->Statistics()->hasChannelFieldValue(CH0, FLD_EVT_LOG)) {
|
||||||
root[i][F("events")] = inv->EventLog()->getEntryCount();
|
invObject[F("events")] = inv->EventLog()->getEntryCount();
|
||||||
} else {
|
} else {
|
||||||
root[i][F("events")] = -1;
|
invObject[F("events")] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inv->Statistics()->getLastUpdate() > _newestInverterTimestamp) {
|
if (inv->Statistics()->getLastUpdate() > _newestInverterTimestamp) {
|
||||||
_newestInverterTimestamp = inv->Statistics()->getLastUpdate();
|
_newestInverterTimestamp = inv->Statistics()->getLastUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
totalPower += inv->Statistics()->getChannelFieldValue(CH0, FLD_PAC);
|
||||||
|
totalYieldDay += inv->Statistics()->getChannelFieldValue(CH0, FLD_YD);
|
||||||
|
totalYieldTotal += inv->Statistics()->getChannelFieldValue(CH0, FLD_YT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonObject totalObj = root.createNestedObject("total");
|
||||||
|
// todo: Fixed hard coded name, unit and digits
|
||||||
|
addTotalField(totalObj, "Power", totalPower, "W", 1);
|
||||||
|
addTotalField(totalObj, "YieldDay", totalYieldDay, "Wh", 0);
|
||||||
|
addTotalField(totalObj, "YieldTotal", totalYieldTotal, "kWh", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebApiWsLiveClass::addField(JsonVariant& root, uint8_t idx, std::shared_ptr<InverterAbstract> inv, uint8_t channel, uint8_t fieldId, String topic)
|
void WebApiWsLiveClass::addField(JsonObject& root, uint8_t idx, std::shared_ptr<InverterAbstract> inv, uint8_t channel, uint8_t fieldId, String topic)
|
||||||
{
|
{
|
||||||
if (inv->Statistics()->hasChannelFieldValue(channel, fieldId)) {
|
if (inv->Statistics()->hasChannelFieldValue(channel, fieldId)) {
|
||||||
String chanName;
|
String chanName;
|
||||||
@ -132,11 +153,19 @@ void WebApiWsLiveClass::addField(JsonVariant& root, uint8_t idx, std::shared_ptr
|
|||||||
} else {
|
} else {
|
||||||
chanName = topic;
|
chanName = topic;
|
||||||
}
|
}
|
||||||
root[idx][String(channel)][chanName]["v"] = inv->Statistics()->getChannelFieldValue(channel, fieldId);
|
root[String(channel)][chanName]["v"] = inv->Statistics()->getChannelFieldValue(channel, fieldId);
|
||||||
root[idx][String(channel)][chanName]["u"] = inv->Statistics()->getChannelFieldUnit(channel, fieldId);
|
root[String(channel)][chanName]["u"] = inv->Statistics()->getChannelFieldUnit(channel, fieldId);
|
||||||
|
root[String(channel)][chanName]["d"] = inv->Statistics()->getChannelFieldDigits(channel, fieldId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebApiWsLiveClass::addTotalField(JsonObject& root, String name, float value, String unit, uint8_t digits)
|
||||||
|
{
|
||||||
|
root[name]["v"] = value;
|
||||||
|
root[name]["u"] = unit;
|
||||||
|
root[name]["d"] = digits;
|
||||||
|
}
|
||||||
|
|
||||||
void WebApiWsLiveClass::onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len)
|
void WebApiWsLiveClass::onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len)
|
||||||
{
|
{
|
||||||
if (type == WS_EVT_CONNECT) {
|
if (type == WS_EVT_CONNECT) {
|
||||||
@ -152,8 +181,8 @@ void WebApiWsLiveClass::onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketC
|
|||||||
|
|
||||||
void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
|
void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
|
||||||
{
|
{
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(true, 40960U);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, 40960U);
|
||||||
JsonVariant root = response->getRoot().as<JsonVariant>();
|
JsonVariant root = response->getRoot();
|
||||||
|
|
||||||
generateJsonResponse(root);
|
generateJsonResponse(root);
|
||||||
|
|
||||||
|
|||||||
@ -21,18 +21,18 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.2.0",
|
"@rushstack/eslint-patch": "^1.2.0",
|
||||||
"@types/bootstrap": "^5.2.5",
|
"@types/bootstrap": "^5.2.5",
|
||||||
"@types/node": "^18.11.4",
|
"@types/node": "^18.11.8",
|
||||||
"@types/spark-md5": "^3.0.2",
|
"@types/spark-md5": "^3.0.2",
|
||||||
"@vitejs/plugin-vue": "^3.1.2",
|
"@vitejs/plugin-vue": "^3.2.0",
|
||||||
"@vue/eslint-config-typescript": "^11.0.2",
|
"@vue/eslint-config-typescript": "^11.0.2",
|
||||||
"@vue/tsconfig": "^0.1.3",
|
"@vue/tsconfig": "^0.1.3",
|
||||||
"eslint": "^8.26.0",
|
"eslint": "^8.26.0",
|
||||||
"eslint-plugin-vue": "^9.6.0",
|
"eslint-plugin-vue": "^9.7.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"typescript": "^4.8.4",
|
"typescript": "^4.8.4",
|
||||||
"vite": "^3.1.8",
|
"vite": "^3.2.2",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-css-injected-by-js": "^2.1.0",
|
"vite-plugin-css-injected-by-js": "^2.1.1",
|
||||||
"vue-tsc": "^1.0.9"
|
"vue-tsc": "^1.0.9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">
|
<div class="card-header text-bg-primary">
|
||||||
Firmware Information
|
Firmware Information
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">
|
<div class="card-header text-bg-primary">
|
||||||
Hardware Information
|
Hardware Information
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">
|
<div class="card-header text-bg-primary">
|
||||||
Network Interface (Access Point)
|
Network Interface (Access Point)
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">
|
<div class="card-header text-bg-primary">
|
||||||
Network Interface ({{ networkStatus.network_mode }})
|
Network Interface ({{ networkStatus.network_mode }})
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card" :class="{ 'border-info': channelNumber == 0 }">
|
<div class="card" :class="{ 'border-info': channelNumber == 0 }">
|
||||||
<div v-if="channelNumber >= 1" class="card-header">String {{ channelNumber }}</div>
|
<div v-if="channelNumber >= 1" class="card-header">String {{ channelNumber }}</div>
|
||||||
<div v-if="channelNumber == 0" class="card-header bg-info">Phase {{ channelNumber + 1 }}</div>
|
<div v-if="channelNumber == 0" class="card-header text-bg-info">Phase {{ channelNumber + 1 }}</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<table class="table table-striped table-hover">
|
<table class="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
@ -15,7 +15,7 @@
|
|||||||
<tr v-for="(property, key) in channelData" :key="`prop-${key}`">
|
<tr v-for="(property, key) in channelData" :key="`prop-${key}`">
|
||||||
<template v-if="property">
|
<template v-if="property">
|
||||||
<th scope="row">{{ key }}</th>
|
<th scope="row">{{ key }}</th>
|
||||||
<td style="text-align: right">{{ formatNumber(property.v) }}</td>
|
<td style="text-align: right">{{ formatNumber(property.v, property.d) }}</td>
|
||||||
<td>{{ property.u }}</td>
|
<td>{{ property.u }}</td>
|
||||||
</template>
|
</template>
|
||||||
</tr>
|
</tr>
|
||||||
@ -28,6 +28,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, type PropType } from 'vue';
|
import { defineComponent, type PropType } from 'vue';
|
||||||
import type { InverterStatistics } from '@/types/LiveDataStatus';
|
import type { InverterStatistics } from '@/types/LiveDataStatus';
|
||||||
|
import { formatNumber } from '@/utils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
@ -35,11 +36,7 @@ export default defineComponent({
|
|||||||
channelNumber: { type: Number, required: true },
|
channelNumber: { type: Number, required: true },
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
formatNumber(num: number) {
|
formatNumber,
|
||||||
return new Intl.NumberFormat(
|
|
||||||
undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }
|
|
||||||
).format(num);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
55
webapp/src/components/InverterTotalInfo.vue
Normal file
55
webapp/src/components/InverterTotalInfo.vue
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<template>
|
||||||
|
<div class="row row-cols-1 row-cols-md-3 g-3">
|
||||||
|
<div class="col">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header text-bg-success">Total Yield Total</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text text-center">
|
||||||
|
<h2>{{ formatNumber(totalData.YieldTotal.v, totalData.YieldTotal.d) }}
|
||||||
|
<small class="text-muted">{{ totalData.YieldTotal.u }}</small>
|
||||||
|
</h2>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header text-bg-success">Total Yield Day</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text text-center">
|
||||||
|
<h2>{{ formatNumber(totalData.YieldDay.v, totalData.YieldDay.d) }}
|
||||||
|
<small class="text-muted">{{ totalData.YieldDay.u }}</small>
|
||||||
|
</h2>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header text-bg-success">Total Power</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text text-center">
|
||||||
|
<h2>{{ formatNumber(totalData.Power.v, totalData.Power.d) }}
|
||||||
|
<small class="text-muted">{{ totalData.Power.u }}</small>
|
||||||
|
</h2>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, type PropType } from 'vue';
|
||||||
|
import type { Total } from '@/types/LiveDataStatus';
|
||||||
|
import { formatNumber } from '@/utils';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
totalData: { type: Object as PropType<Total>, required: true },
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatNumber,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@ -3,7 +3,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Current Limit</td>
|
<td>Current Limit</td>
|
||||||
<td>{{ formatNumber(limitData.limit) }}%</td>
|
<td>{{ formatNumber(limitData.limit, 2) }}%</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import { formatNumber } from '@/utils';
|
||||||
|
|
||||||
declare interface LimitData {
|
declare interface LimitData {
|
||||||
limit: number,
|
limit: number,
|
||||||
@ -20,14 +21,8 @@ export default defineComponent({
|
|||||||
props: {
|
props: {
|
||||||
limitData: { type: Object as () => LimitData, required: true },
|
limitData: { type: Object as () => LimitData, required: true },
|
||||||
},
|
},
|
||||||
computed: {
|
methods: {
|
||||||
formatNumber() {
|
formatNumber,
|
||||||
return (num: number) => {
|
}
|
||||||
return new Intl.NumberFormat(
|
|
||||||
undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }
|
|
||||||
).format(num)
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">Memory Information</div>
|
<div class="card-header text-bg-primary">Memory Information</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover table-condensed">
|
<table class="table table-hover table-condensed">
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
|
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a class="navbar-brand" href="#">OpenDTU</a>
|
<a class="navbar-brand" href="#"><span class="text-warning"><BIconSun width="30" height="30" class="d-inline-block align-text-top"/></span> OpenDTU</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup"
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup"
|
||||||
aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
|
aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
@ -85,8 +85,12 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
import { BIconSun } from 'bootstrap-icons-vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
BIconSun,
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onClick() {
|
onClick() {
|
||||||
this.$refs.navbarCollapse && (this.$refs.navbarCollapse as HTMLElement).classList.remove("show");
|
this.$refs.navbarCollapse && (this.$refs.navbarCollapse as HTMLElement).classList.remove("show");
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">
|
<div class="card-header text-bg-primary">
|
||||||
Radio Information
|
Radio Information
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -10,8 +10,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Chip Status</th>
|
<th>Chip Status</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': !systemStatus.radio_connected,
|
'text-bg-danger': !systemStatus.radio_connected,
|
||||||
'bg-success': systemStatus.radio_connected,
|
'text-bg-success': systemStatus.radio_connected,
|
||||||
}">
|
}">
|
||||||
<span v-if="systemStatus.radio_connected">connected</span>
|
<span v-if="systemStatus.radio_connected">connected</span>
|
||||||
<span v-else>not connected</span>
|
<span v-else>not connected</span>
|
||||||
@ -20,9 +20,9 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Chip Type</th>
|
<th>Chip Type</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': systemStatus.radio_connected && !systemStatus.radio_pvariant,
|
'text-bg-danger': systemStatus.radio_connected && !systemStatus.radio_pvariant,
|
||||||
'bg-success': systemStatus.radio_connected && systemStatus.radio_pvariant,
|
'text-bg-success': systemStatus.radio_connected && systemStatus.radio_pvariant,
|
||||||
'bg-secondary': !systemStatus.radio_connected,
|
'text-bg-secondary': !systemStatus.radio_connected,
|
||||||
}">
|
}">
|
||||||
<span
|
<span
|
||||||
v-if="systemStatus.radio_connected && systemStatus.radio_pvariant">nRF24L01+</span>
|
v-if="systemStatus.radio_connected && systemStatus.radio_pvariant">nRF24L01+</span>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">
|
<div class="card-header text-bg-primary">
|
||||||
WiFi Information (Access Point)
|
WiFi Information (Access Point)
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -10,8 +10,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': !networkStatus.ap_status,
|
'text-bg-danger': !networkStatus.ap_status,
|
||||||
'bg-success': networkStatus.ap_status,
|
'text-bg-success': networkStatus.ap_status,
|
||||||
}">
|
}">
|
||||||
<span v-if="networkStatus.ap_status">enabled</span>
|
<span v-if="networkStatus.ap_status">enabled</span>
|
||||||
<span v-else>disabled</span>
|
<span v-else>disabled</span>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">
|
<div class="card-header text-bg-primary">
|
||||||
WiFi Information (Station)
|
WiFi Information (Station)
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -10,8 +10,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': !networkStatus.sta_status,
|
'text-bg-danger': !networkStatus.sta_status,
|
||||||
'bg-success': networkStatus.sta_status,
|
'text-bg-success': networkStatus.sta_status,
|
||||||
}">
|
}">
|
||||||
<span v-if="networkStatus.sta_status">enabled</span>
|
<span v-if="networkStatus.sta_status">enabled</span>
|
||||||
<span v-else>disabled</span>
|
<span v-else>disabled</span>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
export interface ValueObject {
|
export interface ValueObject {
|
||||||
v: number, // value
|
v: number, // value
|
||||||
u: string, // unit
|
u: string, // unit
|
||||||
|
d: number, // digits
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface InverterStatistics {
|
export interface InverterStatistics {
|
||||||
@ -30,7 +31,16 @@ export interface Inverter {
|
|||||||
[key: number]: InverterStatistics,
|
[key: number]: InverterStatistics,
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface Inverters extends Array<Inverter>{};
|
export interface Total {
|
||||||
|
Power: ValueObject,
|
||||||
|
YieldDay: ValueObject,
|
||||||
|
YieldTotal: ValueObject,
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface LiveData {
|
||||||
|
inverters: Inverter[],
|
||||||
|
total: Total,
|
||||||
|
}
|
||||||
|
|
||||||
// Ve.Direct
|
// Ve.Direct
|
||||||
export interface Vedirect {
|
export interface Vedirect {
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
import { timestampToString } from './time';
|
import { timestampToString } from './time';
|
||||||
|
import { formatNumber } from './number';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
timestampToString,
|
timestampToString,
|
||||||
|
formatNumber,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
timestampToString,
|
timestampToString,
|
||||||
|
formatNumber,
|
||||||
}
|
}
|
||||||
5
webapp/src/utils/number.ts
Normal file
5
webapp/src/utils/number.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export const formatNumber = (num: number, digits: number): string => {
|
||||||
|
return new Intl.NumberFormat(
|
||||||
|
undefined, { minimumFractionDigits: digits, maximumFractionDigits: digits }
|
||||||
|
).format(num);
|
||||||
|
}
|
||||||
@ -5,7 +5,7 @@
|
|||||||
<h2 class="accordion-header" id="headingOne">
|
<h2 class="accordion-header" id="headingOne">
|
||||||
<button class="accordion-button" type="button" data-bs-toggle="collapse"
|
<button class="accordion-button" type="button" data-bs-toggle="collapse"
|
||||||
data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
|
data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
|
||||||
<span class="badge bg-secondary">
|
<span class="badge text-bg-secondary">
|
||||||
<BIconInfoCircle class="fs-4" />
|
<BIconInfoCircle class="fs-4" />
|
||||||
</span> Project Origin
|
</span> Project Origin
|
||||||
</button>
|
</button>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
<h2 class="accordion-header" id="headingTwo">
|
<h2 class="accordion-header" id="headingTwo">
|
||||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
||||||
data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
|
data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
|
||||||
<span class="badge bg-secondary">
|
<span class="badge text-bg-secondary">
|
||||||
<BIconActivity class="fs-4" />
|
<BIconActivity class="fs-4" />
|
||||||
</span> News & Updates
|
</span> News & Updates
|
||||||
</button>
|
</button>
|
||||||
@ -58,7 +58,7 @@
|
|||||||
<h2 class="accordion-header" id="headingThree">
|
<h2 class="accordion-header" id="headingThree">
|
||||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
||||||
data-bs-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
|
data-bs-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
|
||||||
<span class="badge bg-secondary">
|
<span class="badge text-bg-secondary">
|
||||||
<BIconBug class="fs-4" />
|
<BIconBug class="fs-4" />
|
||||||
</span> Error Reporting
|
</span> Error Reporting
|
||||||
</button>
|
</button>
|
||||||
@ -75,7 +75,7 @@
|
|||||||
<h2 class="accordion-header" id="headingFour">
|
<h2 class="accordion-header" id="headingFour">
|
||||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
||||||
data-bs-target="#collapseFour" aria-expanded="false" aria-controls="collapseFour">
|
data-bs-target="#collapseFour" aria-expanded="false" aria-controls="collapseFour">
|
||||||
<span class="badge bg-secondary">
|
<span class="badge text-bg-secondary">
|
||||||
<BIconChat class="fs-4" />
|
<BIconChat class="fs-4" />
|
||||||
</span> Discussion
|
</span> Discussion
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
</BootstrapAlert>
|
</BootstrapAlert>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">Backup: Configuration File Backup</div>
|
<div class="card-header text-bg-primary">Backup: Configuration File Backup</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
Backup the configuration file
|
Backup the configuration file
|
||||||
<button class="btn btn-primary" @click="downloadConfig">Backup
|
<button class="btn btn-primary" @click="downloadConfig">Backup
|
||||||
@ -14,7 +14,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mt-5">
|
<div class="card mt-5">
|
||||||
<div class="card-header text-white bg-primary">Restore: Restore the Configuration File</div>
|
<div class="card-header text-bg-primary">Restore: Restore the Configuration File</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
|
|
||||||
<div v-if="!uploading && UploadError != ''">
|
<div v-if="!uploading && UploadError != ''">
|
||||||
@ -66,7 +66,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mt-5">
|
<div class="card mt-5">
|
||||||
<div class="card-header text-white bg-primary">Initialize: Perform Factory Reset</div>
|
<div class="card-header text-bg-primary">Initialize: Perform Factory Reset</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
|
|
||||||
<button class="btn btn-danger" @click="onFactoryResetModal">Restore Factory-Default Settings
|
<button class="btn btn-danger" @click="onFactoryResetModal">Restore Factory-Default Settings
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<form @submit="saveDtuConfig">
|
<form @submit="saveDtuConfig">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">DTU Configuration</div>
|
<div class="card-header text-bg-primary">DTU Configuration</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="inputDtuSerial" class="col-sm-2 col-form-label">Serial:</label>
|
<label for="inputDtuSerial" class="col-sm-2 col-form-label">Serial:</label>
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="!loading && !uploading && OTAError != ''" class="card">
|
<div v-if="!loading && !uploading && OTAError != ''" class="card">
|
||||||
<div class="card-header text-white bg-danger">OTA Error</div>
|
<div class="card-header text-bg-danger">OTA Error</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<p class="h1 mb-2">
|
<p class="h1 mb-2">
|
||||||
<BIconExclamationCircleFill />
|
<BIconExclamationCircleFill />
|
||||||
@ -30,12 +30,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="!loading && !uploading && OTASuccess" class="card">
|
<div v-else-if="!loading && !uploading && OTASuccess" class="card">
|
||||||
<div class="card-header text-white bg-success">OTA Status</div>
|
<div class="card-header text-bg-success">OTA Status</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<span class="h1 mb-2">
|
<span class="h1 mb-2">
|
||||||
<BIconCheckCircle />
|
<BIconCheckCircle />
|
||||||
</span>
|
</span>
|
||||||
<span> OTA Success </span>
|
<span> OTA Success. The unit has been automatically restarted and will be available again in a few moments. </span>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<button class="btn btn-primary" @click="clear">
|
<button class="btn btn-primary" @click="clear">
|
||||||
@ -45,7 +45,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="!loading && !uploading" class="card">
|
<div v-else-if="!loading && !uploading" class="card">
|
||||||
<div class="card-header text-white bg-primary">Firmware Upload</div>
|
<div class="card-header text-bg-primary">Firmware Upload</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<div class="form-group pt-2 mt-3">
|
<div class="form-group pt-2 mt-3">
|
||||||
<input class="form-control" type="file" ref="file" accept=".bin,.bin.gz" @change="uploadOTA" />
|
<input class="form-control" type="file" ref="file" accept=".bin,.bin.gz" @change="uploadOTA" />
|
||||||
@ -54,7 +54,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="!loading && uploading" class="card">
|
<div v-else-if="!loading && uploading" class="card">
|
||||||
<div class="card-header text-white bg-primary">Upload Progress</div>
|
<div class="card-header text-bg-primary">Upload Progress</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<div class="progress">
|
<div class="progress">
|
||||||
<div class="progress-bar" role="progressbar" :style="{ width: progress + '%' }"
|
<div class="progress-bar" role="progressbar" :style="{ width: progress + '%' }"
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasePage :title="'Live Data'" :isLoading="dataLoading" :isWideScreen="true">
|
<BasePage :title="'Live Data'" :isLoading="dataLoading" :isWideScreen="true">
|
||||||
|
<InverterTotalInfo :totalData="liveData.total" /><br />
|
||||||
<div class="row gy-3">
|
<div class="row gy-3">
|
||||||
<div class="col-sm-3 col-md-2" :style="[inverterData.length == 1 ? {'display': 'none' } : {}]">
|
<div class="col-sm-3 col-md-2" :style="[inverterData.length == 1 ? { 'display': 'none' } : {}]">
|
||||||
<div class="nav nav-pills row-cols-sm-1" id="v-pills-tab" role="tablist" aria-orientation="vertical">
|
<div class="nav nav-pills row-cols-sm-1" id="v-pills-tab" role="tablist" aria-orientation="vertical">
|
||||||
<button v-for="inverter in inverterData" :key="inverter.serial" class="nav-link"
|
<button v-for="inverter in inverterData" :key="inverter.serial" class="nav-link"
|
||||||
:id="'v-pills-' + inverter.serial + '-tab'" data-bs-toggle="pill"
|
:id="'v-pills-' + inverter.serial + '-tab'" data-bs-toggle="pill"
|
||||||
@ -15,17 +16,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-content" id="v-pills-tabContent" :class="{'col-sm-9 col-md-10': inverterData.length > 1,
|
<div class="tab-content" id="v-pills-tabContent" :class="{
|
||||||
'col-sm-12 col-md-12': inverterData.length == 1 }">
|
'col-sm-9 col-md-10': inverterData.length > 1,
|
||||||
|
'col-sm-12 col-md-12': inverterData.length == 1
|
||||||
|
}">
|
||||||
<div v-for="inverter in inverterData" :key="inverter.serial" class="tab-pane fade show"
|
<div v-for="inverter in inverterData" :key="inverter.serial" class="tab-pane fade show"
|
||||||
:id="'v-pills-' + inverter.serial" role="tabpanel"
|
:id="'v-pills-' + inverter.serial" role="tabpanel"
|
||||||
:aria-labelledby="'v-pills-' + inverter.serial + '-tab'" tabindex="0">
|
:aria-labelledby="'v-pills-' + inverter.serial + '-tab'" tabindex="0">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary d-flex justify-content-between align-items-center"
|
<div class="card-header d-flex justify-content-between align-items-center"
|
||||||
:class="{
|
:class="{
|
||||||
'bg-danger': !inverter.reachable,
|
'text-bg-danger': !inverter.reachable,
|
||||||
'bg-warning': inverter.reachable && !inverter.producing,
|
'text-bg-warning': inverter.reachable && !inverter.producing,
|
||||||
'bg-primary': inverter.reachable && inverter.producing,
|
'text-bg-primary': inverter.reachable && inverter.producing,
|
||||||
}">
|
}">
|
||||||
<div class="p-1 flex-grow-1">
|
<div class="p-1 flex-grow-1">
|
||||||
<div class="d-flex flex-wrap">
|
<div class="d-flex flex-wrap">
|
||||||
@ -37,9 +40,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div style="padding-right: 2em;">
|
<div style="padding-right: 2em;">
|
||||||
Current Limit: <template v-if="inverter.limit_absolute > -1"> {{
|
Current Limit: <template v-if="inverter.limit_absolute > -1"> {{
|
||||||
inverter.limit_absolute.toFixed(0) }}W | </template>{{
|
formatNumber(inverter.limit_absolute, 0)
|
||||||
inverter.limit_relative.toFixed(0)
|
}} W | </template>{{ formatNumber(inverter.limit_relative, 0) }} %
|
||||||
}}%
|
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-right: 2em;">
|
<div style="padding-right: 2em;">
|
||||||
Data Age: {{ inverter.data_age }} seconds
|
Data Age: {{ inverter.data_age }} seconds
|
||||||
@ -77,7 +79,7 @@
|
|||||||
@click="onShowEventlog(inverter.serial)" title="Show Eventlog">
|
@click="onShowEventlog(inverter.serial)" title="Show Eventlog">
|
||||||
<BIconJournalText style="font-size:24px;" />
|
<BIconJournalText style="font-size:24px;" />
|
||||||
<span
|
<span
|
||||||
class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
|
class="position-absolute top-0 start-100 translate-middle badge rounded-pill text-bg-danger">
|
||||||
{{ inverter.events }}
|
{{ inverter.events }}
|
||||||
<span class="visually-hidden">unread messages</span>
|
<span class="visually-hidden">unread messages</span>
|
||||||
</span>
|
</span>
|
||||||
@ -180,15 +182,16 @@
|
|||||||
Limit:</label>
|
Limit:</label>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="number" class="form-control" id="inputCurrentLimit"
|
<input type="text" class="form-control" id="inputCurrentLimit"
|
||||||
aria-describedby="currentLimitType" v-model="currentLimitRelative" disabled />
|
aria-describedby="currentLimitType" v-model="currentLimitRelative"
|
||||||
|
disabled />
|
||||||
<span class="input-group-text" id="currentLimitType">%</span>
|
<span class="input-group-text" id="currentLimitType">%</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-sm-4" v-if="currentLimitList.max_power > 0">
|
<div class="col-sm-4" v-if="currentLimitList.max_power > 0">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="number" class="form-control" id="inputCurrentLimitAbsolute"
|
<input type="text" class="form-control" id="inputCurrentLimitAbsolute"
|
||||||
aria-describedby="currentLimitTypeAbsolute" v-model="currentLimitAbsolute"
|
aria-describedby="currentLimitTypeAbsolute" v-model="currentLimitAbsolute"
|
||||||
disabled />
|
disabled />
|
||||||
<span class="input-group-text" id="currentLimitTypeAbsolute">W</span>
|
<span class="input-group-text" id="currentLimitTypeAbsolute">W</span>
|
||||||
@ -201,10 +204,10 @@
|
|||||||
Status:</label>
|
Status:</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<span class="badge" :class="{
|
<span class="badge" :class="{
|
||||||
'bg-danger': currentLimitList.limit_set_status == 'Failure',
|
'text-bg-danger': currentLimitList.limit_set_status == 'Failure',
|
||||||
'bg-warning': currentLimitList.limit_set_status == 'Pending',
|
'text-bg-warning': currentLimitList.limit_set_status == 'Pending',
|
||||||
'bg-success': currentLimitList.limit_set_status == 'Ok',
|
'text-bg-success': currentLimitList.limit_set_status == 'Ok',
|
||||||
'bg-secondary': currentLimitList.limit_set_status == 'Unknown',
|
'text-bg-secondary': currentLimitList.limit_set_status == 'Unknown',
|
||||||
}">
|
}">
|
||||||
{{ currentLimitList.limit_set_status }}
|
{{ currentLimitList.limit_set_status }}
|
||||||
</span>
|
</span>
|
||||||
@ -276,10 +279,10 @@
|
|||||||
Status:</label>
|
Status:</label>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<span class="badge" :class="{
|
<span class="badge" :class="{
|
||||||
'bg-danger': successCommandPower == 'Failure',
|
'text-bg-danger': successCommandPower == 'Failure',
|
||||||
'bg-warning': successCommandPower == 'Pending',
|
'text-bg-warning': successCommandPower == 'Pending',
|
||||||
'bg-success': successCommandPower == 'Ok',
|
'text-bg-success': successCommandPower == 'Ok',
|
||||||
'bg-secondary': successCommandPower == 'Unknown',
|
'text-bg-secondary': successCommandPower == 'Unknown',
|
||||||
}">
|
}">
|
||||||
{{ successCommandPower }}
|
{{ successCommandPower }}
|
||||||
</span>
|
</span>
|
||||||
@ -330,17 +333,20 @@ import EventLog from '@/components/EventLog.vue';
|
|||||||
import DevInfo from '@/components/DevInfo.vue';
|
import DevInfo from '@/components/DevInfo.vue';
|
||||||
import BootstrapAlert from '@/components/BootstrapAlert.vue';
|
import BootstrapAlert from '@/components/BootstrapAlert.vue';
|
||||||
import InverterChannelInfo from "@/components/InverterChannelInfo.vue";
|
import InverterChannelInfo from "@/components/InverterChannelInfo.vue";
|
||||||
|
import InverterTotalInfo from '@/components/InverterTotalInfo.vue';
|
||||||
import VedirectView from '@/views/VedirectView.vue';
|
import VedirectView from '@/views/VedirectView.vue';
|
||||||
import type { DevInfoStatus } from '@/types/DevInfoStatus';
|
import type { DevInfoStatus } from '@/types/DevInfoStatus';
|
||||||
import type { EventlogItems } from '@/types/EventlogStatus';
|
import type { EventlogItems } from '@/types/EventlogStatus';
|
||||||
import type { Inverters } from '@/types/LiveDataStatus';
|
import type { LiveData, Inverter } from '@/types/LiveDataStatus';
|
||||||
import type { LimitStatus } from '@/types/LimitStatus';
|
import type { LimitStatus } from '@/types/LimitStatus';
|
||||||
import type { LimitConfig } from '@/types/LimitConfig';
|
import type { LimitConfig } from '@/types/LimitConfig';
|
||||||
|
import { formatNumber } from '@/utils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
BasePage,
|
BasePage,
|
||||||
InverterChannelInfo,
|
InverterChannelInfo,
|
||||||
|
InverterTotalInfo,
|
||||||
EventLog,
|
EventLog,
|
||||||
DevInfo,
|
DevInfo,
|
||||||
BootstrapAlert,
|
BootstrapAlert,
|
||||||
@ -362,7 +368,7 @@ export default defineComponent({
|
|||||||
heartInterval: 0,
|
heartInterval: 0,
|
||||||
dataAgeInterval: 0,
|
dataAgeInterval: 0,
|
||||||
dataLoading: true,
|
dataLoading: true,
|
||||||
inverterData: [] as Inverters,
|
liveData: {} as LiveData,
|
||||||
isFirstFetchAfterConnect: true,
|
isFirstFetchAfterConnect: true,
|
||||||
eventLogView: {} as bootstrap.Modal,
|
eventLogView: {} as bootstrap.Modal,
|
||||||
eventLogList: {} as EventlogItems,
|
eventLogList: {} as EventlogItems,
|
||||||
@ -377,7 +383,7 @@ export default defineComponent({
|
|||||||
currentLimitList: {} as LimitStatus,
|
currentLimitList: {} as LimitStatus,
|
||||||
targetLimitList: {} as LimitConfig,
|
targetLimitList: {} as LimitConfig,
|
||||||
|
|
||||||
targetLimitMin: 10,
|
targetLimitMin: 2,
|
||||||
targetLimitMax: 100,
|
targetLimitMax: 100,
|
||||||
targetLimitTypeText: "Relative (%)",
|
targetLimitTypeText: "Relative (%)",
|
||||||
targetLimitType: 1,
|
targetLimitType: 1,
|
||||||
@ -428,23 +434,27 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
currentLimitAbsolute(): number {
|
currentLimitAbsolute(): string {
|
||||||
if (this.currentLimitList.max_power > 0) {
|
if (this.currentLimitList.max_power > 0) {
|
||||||
return Number((this.currentLimitList.limit_relative * this.currentLimitList.max_power / 100).toFixed(1));
|
return formatNumber(this.currentLimitList.limit_relative * this.currentLimitList.max_power / 100, 2);
|
||||||
}
|
}
|
||||||
return 0;
|
return "0";
|
||||||
},
|
},
|
||||||
currentLimitRelative(): number {
|
currentLimitRelative(): string {
|
||||||
return Number((this.currentLimitList.limit_relative).toFixed(1));
|
return formatNumber(this.currentLimitList.limit_relative, 2);
|
||||||
|
},
|
||||||
|
inverterData(): Inverter[] {
|
||||||
|
return this.liveData.inverters;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
formatNumber,
|
||||||
getInitialData() {
|
getInitialData() {
|
||||||
this.dataLoading = true;
|
this.dataLoading = true;
|
||||||
fetch("/api/livedata/status")
|
fetch("/api/livedata/status")
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.inverterData = data;
|
this.liveData = data;
|
||||||
this.dataLoading = false;
|
this.dataLoading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -459,7 +469,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
this.socket.onmessage = (event) => {
|
this.socket.onmessage = (event) => {
|
||||||
console.log(event);
|
console.log(event);
|
||||||
this.inverterData = JSON.parse(event.data);
|
this.liveData = JSON.parse(event.data);
|
||||||
this.dataLoading = false;
|
this.dataLoading = false;
|
||||||
this.heartCheck(); // Reset heartbeat detection
|
this.heartCheck(); // Reset heartbeat detection
|
||||||
};
|
};
|
||||||
@ -585,7 +595,7 @@ export default defineComponent({
|
|||||||
onSelectType(type: number) {
|
onSelectType(type: number) {
|
||||||
if (type == 1) {
|
if (type == 1) {
|
||||||
this.targetLimitTypeText = "Relative (%)";
|
this.targetLimitTypeText = "Relative (%)";
|
||||||
this.targetLimitMin = 10;
|
this.targetLimitMin = 2;
|
||||||
this.targetLimitMax = 100;
|
this.targetLimitMax = 100;
|
||||||
} else {
|
} else {
|
||||||
this.targetLimitTypeText = "Absolute (W)";
|
this.targetLimitTypeText = "Absolute (W)";
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
</BootstrapAlert>
|
</BootstrapAlert>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">Add a new Inverter</div>
|
<div class="card-header text-bg-primary">Add a new Inverter</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form class="form-inline" v-on:submit.prevent="onSubmit">
|
<form class="form-inline" v-on:submit.prevent="onSubmit">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -30,7 +30,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mt-5">
|
<div class="card mt-5">
|
||||||
<div class="card-header text-white bg-primary">Inverter List</div>
|
<div class="card-header text-bg-primary">Inverter List</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<form @submit="saveMqttConfig">
|
<form @submit="saveMqttConfig">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">MqTT Configuration</div>
|
<div class="card-header text-bg-primary">MqTT Configuration</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label class="col-sm-4 form-check-label" for="inputMqtt">Enable MqTT</label>
|
<label class="col-sm-4 form-check-label" for="inputMqtt">Enable MqTT</label>
|
||||||
@ -32,7 +32,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mt-5" v-show="mqttConfigList.mqtt_enabled">
|
<div class="card mt-5" v-show="mqttConfigList.mqtt_enabled">
|
||||||
<div class="card-header text-white bg-primary">
|
<div class="card-header text-bg-primary">
|
||||||
MqTT Broker Parameter
|
MqTT Broker Parameter
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -127,7 +127,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mt-5" v-show="mqttConfigList.mqtt_enabled">
|
<div class="card mt-5" v-show="mqttConfigList.mqtt_enabled">
|
||||||
<div class="card-header text-white bg-primary">LWT Parameters</div>
|
<div class="card-header text-bg-primary">LWT Parameters</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="inputLwtTopic" class="col-sm-2 col-form-label">LWT Topic:</label>
|
<label for="inputLwtTopic" class="col-sm-2 col-form-label">LWT Topic:</label>
|
||||||
@ -164,7 +164,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mt-5" v-show="mqttConfigList.mqtt_enabled && mqttConfigList.mqtt_hass_enabled">
|
<div class="card mt-5" v-show="mqttConfigList.mqtt_enabled && mqttConfigList.mqtt_hass_enabled">
|
||||||
<div class="card-header text-white bg-primary">Home Assistant MQTT Auto Discovery Parameters</div>
|
<div class="card-header text-bg-primary">Home Assistant MQTT Auto Discovery Parameters</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="inputHassTopic" class="col-sm-2 col-form-label">Prefix Topic:</label>
|
<label for="inputHassTopic" class="col-sm-2 col-form-label">Prefix Topic:</label>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasePage :title="'MqTT Info'" :isLoading="dataLoading">
|
<BasePage :title="'MqTT Info'" :isLoading="dataLoading">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">Configuration Summary</div>
|
<div class="card-header text-bg-primary">Configuration Summary</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover table-condensed">
|
<table class="table table-hover table-condensed">
|
||||||
@ -9,8 +9,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': !mqttDataList.mqtt_enabled,
|
'text-bg-danger': !mqttDataList.mqtt_enabled,
|
||||||
'bg-success': mqttDataList.mqtt_enabled,
|
'text-bg-success': mqttDataList.mqtt_enabled,
|
||||||
}">
|
}">
|
||||||
<span v-if="mqttDataList.mqtt_enabled">enabled</span>
|
<span v-if="mqttDataList.mqtt_enabled">enabled</span>
|
||||||
<span v-else>disabled</span>
|
<span v-else>disabled</span>
|
||||||
@ -39,8 +39,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Retain</th>
|
<th>Retain</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': !mqttDataList.mqtt_retain,
|
'text-bg-danger': !mqttDataList.mqtt_retain,
|
||||||
'bg-success': mqttDataList.mqtt_retain,
|
'text-bg-success': mqttDataList.mqtt_retain,
|
||||||
}">
|
}">
|
||||||
<span v-if="mqttDataList.mqtt_retain">enabled</span>
|
<span v-if="mqttDataList.mqtt_retain">enabled</span>
|
||||||
<span v-else>disabled</span>
|
<span v-else>disabled</span>
|
||||||
@ -49,8 +49,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>TLS</th>
|
<th>TLS</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': !mqttDataList.mqtt_tls,
|
'text-bg-danger': !mqttDataList.mqtt_tls,
|
||||||
'bg-success': mqttDataList.mqtt_tls,
|
'text-bg-success': mqttDataList.mqtt_tls,
|
||||||
}">
|
}">
|
||||||
<span v-if="mqttDataList.mqtt_tls">enabled</span>
|
<span v-if="mqttDataList.mqtt_tls">enabled</span>
|
||||||
<span v-else>disabled</span>
|
<span v-else>disabled</span>
|
||||||
@ -67,7 +67,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mt-5">
|
<div class="card mt-5">
|
||||||
<div class="card-header text-white bg-primary">Home Assistant MQTT Auto Discovery Configuration Summary
|
<div class="card-header text-bg-primary">Home Assistant MQTT Auto Discovery Configuration Summary
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
@ -76,8 +76,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': !mqttDataList.mqtt_hass_enabled,
|
'text-bg-danger': !mqttDataList.mqtt_hass_enabled,
|
||||||
'bg-success': mqttDataList.mqtt_hass_enabled,
|
'text-bg-success': mqttDataList.mqtt_hass_enabled,
|
||||||
}">
|
}">
|
||||||
<span v-if="mqttDataList.mqtt_hass_enabled">enabled</span>
|
<span v-if="mqttDataList.mqtt_hass_enabled">enabled</span>
|
||||||
<span v-else>disabled</span>
|
<span v-else>disabled</span>
|
||||||
@ -90,8 +90,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Retain</th>
|
<th>Retain</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': !mqttDataList.mqtt_hass_retain,
|
'text-bg-danger': !mqttDataList.mqtt_hass_retain,
|
||||||
'bg-success': mqttDataList.mqtt_hass_retain,
|
'text-bg-success': mqttDataList.mqtt_hass_retain,
|
||||||
}">
|
}">
|
||||||
<span v-if="mqttDataList.mqtt_hass_retain">enabled</span>
|
<span v-if="mqttDataList.mqtt_hass_retain">enabled</span>
|
||||||
<span v-else>disabled</span>
|
<span v-else>disabled</span>
|
||||||
@ -100,8 +100,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Expire</th>
|
<th>Expire</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': !mqttDataList.mqtt_hass_expire,
|
'text-bg-danger': !mqttDataList.mqtt_hass_expire,
|
||||||
'bg-success': mqttDataList.mqtt_hass_expire,
|
'text-bg-success': mqttDataList.mqtt_hass_expire,
|
||||||
}">
|
}">
|
||||||
<span v-if="mqttDataList.mqtt_hass_expire">enabled</span>
|
<span v-if="mqttDataList.mqtt_hass_expire">enabled</span>
|
||||||
<span v-else>disabled</span>
|
<span v-else>disabled</span>
|
||||||
@ -110,8 +110,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Individual Panels</th>
|
<th>Individual Panels</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': !mqttDataList.mqtt_hass_individualpanels,
|
'text-bg-danger': !mqttDataList.mqtt_hass_individualpanels,
|
||||||
'bg-success': mqttDataList.mqtt_hass_individualpanels,
|
'text-bg-success': mqttDataList.mqtt_hass_individualpanels,
|
||||||
}">
|
}">
|
||||||
<span v-if="mqttDataList.mqtt_hass_individualpanels">enabled</span>
|
<span v-if="mqttDataList.mqtt_hass_individualpanels">enabled</span>
|
||||||
<span v-else>disabled</span>
|
<span v-else>disabled</span>
|
||||||
@ -124,7 +124,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mt-5">
|
<div class="card mt-5">
|
||||||
<div class="card-header text-white bg-primary">Runtime Summary</div>
|
<div class="card-header text-bg-primary">Runtime Summary</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover table-condensed">
|
<table class="table table-hover table-condensed">
|
||||||
@ -132,8 +132,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Connection Status</th>
|
<th>Connection Status</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': !mqttDataList.mqtt_connected,
|
'text-bg-danger': !mqttDataList.mqtt_connected,
|
||||||
'bg-success': mqttDataList.mqtt_connected,
|
'text-bg-success': mqttDataList.mqtt_connected,
|
||||||
}">
|
}">
|
||||||
<span v-if="mqttDataList.mqtt_connected">connected</span>
|
<span v-if="mqttDataList.mqtt_connected">connected</span>
|
||||||
<span v-else>disconnected</span>
|
<span v-else>disconnected</span>
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<form @submit="saveNetworkConfig">
|
<form @submit="saveNetworkConfig">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">WiFi Configuration</div>
|
<div class="card-header text-bg-primary">WiFi Configuration</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="inputSSID" class="col-sm-2 col-form-label">WiFi SSID:</label>
|
<label for="inputSSID" class="col-sm-2 col-form-label">WiFi SSID:</label>
|
||||||
@ -50,7 +50,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card" v-show="!networkConfigList.dhcp">
|
<div class="card" v-show="!networkConfigList.dhcp">
|
||||||
<div class="card-header text-white bg-primary">
|
<div class="card-header text-bg-primary">
|
||||||
Static IP Configuration
|
Static IP Configuration
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<form @submit="saveNtpConfig">
|
<form @submit="saveNtpConfig">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">NTP Configuration</div>
|
<div class="card-header text-bg-primary">NTP Configuration</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="inputNtpServer" class="col-sm-2 col-form-label">Time Server:</label>
|
<label for="inputNtpServer" class="col-sm-2 col-form-label">Time Server:</label>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">Manual Time Synchronization</div>
|
<div class="card-header text-bg-primary">Manual Time Synchronization</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="currentMcuTime" class="col-sm-2 col-form-label">Current OpenDTU Time:</label>
|
<label for="currentMcuTime" class="col-sm-2 col-form-label">Current OpenDTU Time:</label>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasePage :title="'NTP Info'" :isLoading="dataLoading">
|
<BasePage :title="'NTP Info'" :isLoading="dataLoading">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">Configuration Summary</div>
|
<div class="card-header text-bg-primary">Configuration Summary</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover table-condensed">
|
<table class="table table-hover table-condensed">
|
||||||
@ -25,7 +25,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mt-5">
|
<div class="card mt-5">
|
||||||
<div class="card-header text-white bg-primary">Current Time</div>
|
<div class="card-header text-bg-primary">Current Time</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover table-condensed">
|
<table class="table table-hover table-condensed">
|
||||||
@ -33,8 +33,8 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<td class="badge" :class="{
|
<td class="badge" :class="{
|
||||||
'bg-danger': !ntpDataList.ntp_status,
|
'text-bg-danger': !ntpDataList.ntp_status,
|
||||||
'bg-success': ntpDataList.ntp_status,
|
'text-bg-success': ntpDataList.ntp_status,
|
||||||
}">
|
}">
|
||||||
<span v-if="ntpDataList.ntp_status">synced</span>
|
<span v-if="ntpDataList.ntp_status">synced</span>
|
||||||
<span v-else>not synced</span>
|
<span v-else>not synced</span>
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<form @submit="savePasswordConfig">
|
<form @submit="savePasswordConfig">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">Admin password</div>
|
<div class="card-header text-bg-primary">Admin password</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="inputPassword" class="col-sm-2 col-form-label">Password:</label>
|
<label for="inputPassword" class="col-sm-2 col-form-label">Password:</label>
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
<template v-if="!dataLoading">
|
<template v-if="!dataLoading">
|
||||||
<form @submit="saveVedirectConfig">
|
<form @submit="saveVedirectConfig">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">Ve.direct Configuration</div>
|
<div class="card-header bg-primary">Ve.direct Configuration</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label class="col-sm-2 form-check-label" for="inputVedirect">Enable Ve.direct</label>
|
<label class="col-sm-2 form-check-label" for="inputVedirect">Enable Ve.direct</label>
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<template v-if="!dataLoading">
|
<template v-if="!dataLoading">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary">Configuration Summary</div>
|
<div class="card-header bg-primary">Configuration Summary</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover table-condensed">
|
<table class="table table-hover table-condensed">
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
<div class="row gy-3">
|
<div class="row gy-3">
|
||||||
<div class="tab-content col-sm-12 col-md-12" id="v-pills-tabContent">
|
<div class="tab-content col-sm-12 col-md-12" id="v-pills-tabContent">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header text-white bg-primary d-flex justify-content-between align-items-center"
|
<div class="card-header d-flex justify-content-between align-items-center"
|
||||||
:class="{
|
:class="{
|
||||||
'bg-danger': vedirectData.age_critical,
|
'bg-danger': vedirectData.age_critical,
|
||||||
'bg-primary': !vedirectData.age_critical,
|
'bg-primary': !vedirectData.age_critical,
|
||||||
|
|||||||
@ -99,10 +99,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
|
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
|
||||||
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
|
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
|
||||||
|
|
||||||
"@types/node@^18.11.4":
|
"@types/node@^18.11.8":
|
||||||
version "18.11.4"
|
version "18.11.8"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.4.tgz#7017a52e18dfaad32f55eebd539993014441949c"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.8.tgz#16d222a58d4363a2a359656dd20b28414de5d265"
|
||||||
integrity sha512-BxcJpBu8D3kv/GZkx/gSMz6VnTJREBj/4lbzYOQueUOELkt8WrO6zAcSPmp9uRPEW/d+lUO8QK0W2xnS1hEU0A==
|
integrity sha512-uGwPWlE0Hj972KkHtCDVwZ8O39GmyjfMane1Z3GUBGGnkZ2USDq7SxLpVIiIHpweY9DS0QTDH0Nw7RNBsAAZ5A==
|
||||||
|
|
||||||
"@types/spark-md5@^3.0.2":
|
"@types/spark-md5@^3.0.2":
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
@ -223,10 +223,10 @@
|
|||||||
"@typescript-eslint/types" "5.32.0"
|
"@typescript-eslint/types" "5.32.0"
|
||||||
eslint-visitor-keys "^3.3.0"
|
eslint-visitor-keys "^3.3.0"
|
||||||
|
|
||||||
"@vitejs/plugin-vue@^3.1.2":
|
"@vitejs/plugin-vue@^3.2.0":
|
||||||
version "3.1.2"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-3.1.2.tgz#3cd52114e8871a0b5e7bd7d837469c032e503036"
|
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-3.2.0.tgz#a1484089dd85d6528f435743f84cdd0d215bbb54"
|
||||||
integrity sha512-3zxKNlvA3oNaKDYX0NBclgxTQ1xaFdL7PzwF6zj9tGFziKwmBa3Q/6XcJQxudlT81WxDjEhHmevvIC4Orc1LhQ==
|
integrity sha512-E0tnaL4fr+qkdCNxJ+Xd0yM31UwMkQje76fsDVBBUCoGOUPexu2VDUYHL8P4CwV+zMvWw6nlRw19OnRKmYAJpw==
|
||||||
|
|
||||||
"@volar/language-core@1.0.9":
|
"@volar/language-core@1.0.9":
|
||||||
version "1.0.9"
|
version "1.0.9"
|
||||||
@ -785,10 +785,10 @@ escape-string-regexp@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||||
|
|
||||||
eslint-plugin-vue@^9.6.0:
|
eslint-plugin-vue@^9.7.0:
|
||||||
version "9.6.0"
|
version "9.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.6.0.tgz#5d1825b93d54595b1ba97106843e1d28cf3bb291"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.7.0.tgz#d391b9864f128ea2d1ee4dabeafb5f7c0cea981f"
|
||||||
integrity sha512-zzySkJgVbFCylnG2+9MDF7N+2Rjze2y0bF8GyUNpFOnT8mCMfqqtLDJkHBuYu9N/psW1A6DVbQhPkP92E+qakA==
|
integrity sha512-DrOO3WZCZEwcLsnd3ohFwqCoipGRSTKTBTnLwdhqAbYZtzWl0o7D+D8ZhlmiZvABKTEl8AFsqH1GHGdybyoQmw==
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint-utils "^3.0.0"
|
eslint-utils "^3.0.0"
|
||||||
natural-compare "^1.4.0"
|
natural-compare "^1.4.0"
|
||||||
@ -1633,7 +1633,7 @@ postcss@^8.1.10:
|
|||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
source-map-js "^1.0.2"
|
source-map-js "^1.0.2"
|
||||||
|
|
||||||
postcss@^8.4.16:
|
postcss@^8.4.18:
|
||||||
version "8.4.18"
|
version "8.4.18"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.18.tgz#6d50046ea7d3d66a85e0e782074e7203bc7fbca2"
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.18.tgz#6d50046ea7d3d66a85e0e782074e7203bc7fbca2"
|
||||||
integrity sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==
|
integrity sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==
|
||||||
@ -1706,10 +1706,10 @@ rimraf@^3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
|
|
||||||
rollup@~2.78.0:
|
rollup@^2.79.1:
|
||||||
version "2.78.1"
|
version "2.79.1"
|
||||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.78.1.tgz#52fe3934d9c83cb4f7c4cb5fb75d88591be8648f"
|
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7"
|
||||||
integrity sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==
|
integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.2"
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
@ -1978,20 +1978,20 @@ vite-plugin-compression@^0.5.1:
|
|||||||
debug "^4.3.3"
|
debug "^4.3.3"
|
||||||
fs-extra "^10.0.0"
|
fs-extra "^10.0.0"
|
||||||
|
|
||||||
vite-plugin-css-injected-by-js@^2.1.0:
|
vite-plugin-css-injected-by-js@^2.1.1:
|
||||||
version "2.1.0"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-2.1.0.tgz#3c75c8f2eb41128f6fe22ca9e3eae6bde63231f0"
|
resolved "https://registry.yarnpkg.com/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-2.1.1.tgz#a79275241c61f1c8d55d228f5b2dded450a580e4"
|
||||||
integrity sha512-p5Tn63xfYd1j4Hhnn9YuVMF3t7eLpiHejKNcIeGOWNU60bsw8WXmLQSVGtraw3C6qNz5LnF3S8R1SQLe4/LBYw==
|
integrity sha512-gjIG6iFWde32oRr/bK9CsfN+jdbura2y4GlDzeOiEm6py38ud8dXzFl9zwmHjOjZdr8XEgQ9TovzVGNzp47esw==
|
||||||
|
|
||||||
vite@^3.1.8:
|
vite@^3.2.2:
|
||||||
version "3.1.8"
|
version "3.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/vite/-/vite-3.1.8.tgz#fa29144167d19b773baffd65b3972ea4c12359c9"
|
resolved "https://registry.yarnpkg.com/vite/-/vite-3.2.2.tgz#280762bfaf47bcea1d12698427331c0009ac7c1f"
|
||||||
integrity sha512-m7jJe3nufUbuOfotkntGFupinL/fmuTNuQmiVE7cH2IZMuf4UbfbGYMUT3jVWgGYuRVLY9j8NnrRqgw5rr5QTg==
|
integrity sha512-pLrhatFFOWO9kS19bQ658CnRYzv0WLbsPih6R+iFeEEhDOuYgYCX2rztUViMz/uy/V8cLCJvLFeiOK7RJEzHcw==
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild "^0.15.9"
|
esbuild "^0.15.9"
|
||||||
postcss "^8.4.16"
|
postcss "^8.4.18"
|
||||||
resolve "^1.22.1"
|
resolve "^1.22.1"
|
||||||
rollup "~2.78.0"
|
rollup "^2.79.1"
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.2"
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user