Merge remote-tracking branch
'tbnobody/OpenDTU/master'
This commit is contained in:
commit
366e7dc409
@ -64,6 +64,7 @@ Sends text raw data as difined in VE.Direct spec.
|
||||
* Show inverters internal event log
|
||||
* Show inverter information like firmware version, firmware build date, hardware revision and hardware version
|
||||
* Show and set the current inverter limit
|
||||
* Function to turn the inverter off an on
|
||||
* Uses ESP32 microcontroller and NRF24L01+
|
||||
* Multi-Inverter support
|
||||
* MQTT support (with TLS)
|
||||
@ -95,7 +96,7 @@ Sample Picture:
|
||||
|
||||
Also supported: Board with Ethernet-Connector and Power-over-Ethernet [Olimex ESP32-POE](https://www.olimex.com/Products/IoT/ESP32/ESP32-POE/open-source-hardware)
|
||||
|
||||
#### NRF24L01+ radio board
|
||||
### NRF24L01+ radio board
|
||||
The PLUS sign is IMPORTANT! There are different variants available, with antenna on the printed circuit board or external antenna.
|
||||
|
||||
Sample picture:
|
||||
@ -113,7 +114,7 @@ A heavily incomplete list of trusted hardware shops in germany is:
|
||||
|
||||
This list is for your convenience only, the project is not related to any of these shops.
|
||||
|
||||
#### Power supply
|
||||
### Power supply
|
||||
Use a power suppy with 5V and 1A. The USB cable connected to your PC/Notebook may be powerful enough or may be not.
|
||||
|
||||
|
||||
|
||||
@ -66,4 +66,5 @@ cmd topics are used to set values. Status topics are updated from values set in
|
||||
| [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_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_absolute | W | Set the inverter limit as a absolute value. 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 after around 4 minutes. | Watt (W) |
|
||||
| [serial]/cmd/limit_nonpersistent_absolute | W | Set the inverter limit as a absolute value. 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 after around 4 minutes. | Watt (W) |
|
||||
| [serial]/cmd/power | W | Turn the inverter on (1) or off (0) | 0 or 1 |
|
||||
@ -11,6 +11,7 @@
|
||||
#include "WebApi_mqtt.h"
|
||||
#include "WebApi_network.h"
|
||||
#include "WebApi_ntp.h"
|
||||
#include "WebApi_power.h"
|
||||
#include "WebApi_sysstatus.h"
|
||||
#include "WebApi_webapp.h"
|
||||
#include "WebApi_ws_live.h"
|
||||
@ -38,6 +39,7 @@ private:
|
||||
WebApiMqttClass _webApiMqtt;
|
||||
WebApiNetworkClass _webApiNetwork;
|
||||
WebApiNtpClass _webApiNtp;
|
||||
WebApiPowerClass _webApiPower;
|
||||
WebApiSysstatusClass _webApiSysstatus;
|
||||
WebApiWebappClass _webApiWebapp;
|
||||
WebApiWsLiveClass _webApiWsLive;
|
||||
|
||||
16
include/WebApi_power.h
Normal file
16
include/WebApi_power.h
Normal file
@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
class WebApiPowerClass {
|
||||
public:
|
||||
void init(AsyncWebServer* server);
|
||||
void loop();
|
||||
|
||||
private:
|
||||
void onPowerStatus(AsyncWebServerRequest* request);
|
||||
void onPowerPost(AsyncWebServerRequest* request);
|
||||
|
||||
AsyncWebServer* _server;
|
||||
};
|
||||
@ -46,8 +46,14 @@ void HoymilesClass::loop()
|
||||
iv->resendActivePowerControlRequest(_radio.get());
|
||||
}
|
||||
|
||||
// Set power status if required
|
||||
if (iv->PowerCommand()->getLastPowerCommandSuccess() == CMD_NOK) {
|
||||
Serial.println(F("Resend PowerCommand"));
|
||||
iv->resendPowerControlRequest(_radio.get());
|
||||
}
|
||||
|
||||
// Fetch dev info (but first fetch stats)
|
||||
if (iv->Statistics()->getLastUpdate() > 0 && (iv->DevInfo()->getLastUpdateAll() == 0 || iv->DevInfo()->getLastUpdateSample() == 0)) {
|
||||
if (iv->Statistics()->getLastUpdate() > 0 && (iv->DevInfo()->getLastUpdateAll() == 0 || iv->DevInfo()->getLastUpdateSimple() == 0)) {
|
||||
Serial.println(F("Request device info"));
|
||||
iv->sendDevInfoRequest(_radio.get());
|
||||
}
|
||||
|
||||
@ -28,6 +28,6 @@ bool DevInfoSimpleCommand::handleResponse(InverterAbstract* inverter, fragment_t
|
||||
inverter->DevInfo()->appendFragmentSimple(offs, fragment[i].fragment, fragment[i].len);
|
||||
offs += (fragment[i].len);
|
||||
}
|
||||
inverter->DevInfo()->setLastUpdateSample(millis());
|
||||
inverter->DevInfo()->setLastUpdateSimple(millis());
|
||||
return true;
|
||||
}
|
||||
@ -61,7 +61,7 @@ CommandAbstract* MultiDataCommand::getRequestFrameCommand(uint8_t frame_no)
|
||||
bool MultiDataCommand::handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id)
|
||||
{
|
||||
// All fragments are available --> Check CRC
|
||||
uint16_t crc = 0xffff, crcRcv;
|
||||
uint16_t crc = 0xffff, crcRcv = 0;
|
||||
|
||||
for (uint8_t i = 0; i < max_fragment_id; i++) {
|
||||
if (i == max_fragment_id - 1) {
|
||||
|
||||
56
lib/Hoymiles/src/commands/PowerControlCommand.cpp
Normal file
56
lib/Hoymiles/src/commands/PowerControlCommand.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
#include "PowerControlCommand.h"
|
||||
#include "inverters/InverterAbstract.h"
|
||||
|
||||
#define CRC_SIZE 2
|
||||
|
||||
PowerControlCommand::PowerControlCommand(uint64_t target_address, uint64_t router_address)
|
||||
: DevControlCommand(target_address, router_address)
|
||||
{
|
||||
_payload[10] = 0x00; // TurnOn
|
||||
_payload[11] = 0x00;
|
||||
|
||||
udpateCRC(CRC_SIZE); // 2 byte crc
|
||||
|
||||
_payload_size = 14;
|
||||
|
||||
setTimeout(2000);
|
||||
}
|
||||
|
||||
String PowerControlCommand::getCommandName()
|
||||
{
|
||||
return "PowerControl";
|
||||
}
|
||||
|
||||
bool PowerControlCommand::handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id)
|
||||
{
|
||||
if (!DevControlCommand::handleResponse(inverter, fragment, max_fragment_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
inverter->PowerCommand()->setLastUpdateCommand(millis());
|
||||
inverter->PowerCommand()->setLastPowerCommandSuccess(CMD_OK);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PowerControlCommand::gotTimeout(InverterAbstract* inverter)
|
||||
{
|
||||
inverter->PowerCommand()->setLastPowerCommandSuccess(CMD_NOK);
|
||||
}
|
||||
|
||||
void PowerControlCommand::setPowerOn(bool state)
|
||||
{
|
||||
if (state) {
|
||||
_payload[10] = 0x00; // TurnOn
|
||||
} else {
|
||||
_payload[10] = 0x01; // TurnOff
|
||||
}
|
||||
|
||||
udpateCRC(CRC_SIZE); // 2 byte crc
|
||||
}
|
||||
|
||||
void PowerControlCommand::setRestart()
|
||||
{
|
||||
_payload[10] = 0x02; // Restart
|
||||
|
||||
udpateCRC(CRC_SIZE); // 2 byte crc
|
||||
}
|
||||
16
lib/Hoymiles/src/commands/PowerControlCommand.h
Normal file
16
lib/Hoymiles/src/commands/PowerControlCommand.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "DevControlCommand.h"
|
||||
|
||||
class PowerControlCommand : public DevControlCommand {
|
||||
public:
|
||||
explicit PowerControlCommand(uint64_t target_address = 0, uint64_t router_address = 0);
|
||||
|
||||
virtual String getCommandName();
|
||||
|
||||
virtual bool handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id);
|
||||
virtual void gotTimeout(InverterAbstract* inverter);
|
||||
|
||||
void setPowerOn(bool state);
|
||||
void setRestart();
|
||||
};
|
||||
@ -4,6 +4,7 @@
|
||||
#include "commands/AlarmDataCommand.h"
|
||||
#include "commands/DevInfoAllCommand.h"
|
||||
#include "commands/DevInfoSimpleCommand.h"
|
||||
#include "commands/PowerControlCommand.h"
|
||||
#include "commands/RealTimeRunDataCommand.h"
|
||||
#include "commands/SystemConfigParaCommand.h"
|
||||
|
||||
@ -69,9 +70,9 @@ bool HM_Abstract::sendDevInfoRequest(HoymilesRadio* radio)
|
||||
cmdAll->setTime(now);
|
||||
cmdAll->setTargetAddress(serial());
|
||||
|
||||
DevInfoSimpleCommand* cmdSample = radio->enqueCommand<DevInfoSimpleCommand>();
|
||||
cmdSample->setTime(now);
|
||||
cmdSample->setTargetAddress(serial());
|
||||
DevInfoSimpleCommand* cmdSimple = radio->enqueCommand<DevInfoSimpleCommand>();
|
||||
cmdSimple->setTime(now);
|
||||
cmdSimple->setTargetAddress(serial());
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -110,4 +111,21 @@ bool HM_Abstract::sendActivePowerControlRequest(HoymilesRadio* radio, float limi
|
||||
bool HM_Abstract::resendActivePowerControlRequest(HoymilesRadio* radio)
|
||||
{
|
||||
return sendActivePowerControlRequest(radio, _activePowerControlLimit, _activePowerControlType);
|
||||
}
|
||||
|
||||
bool HM_Abstract::sendPowerControlRequest(HoymilesRadio* radio, bool turnOn)
|
||||
{
|
||||
_powerState = turnOn;
|
||||
|
||||
PowerControlCommand* cmd = radio->enqueCommand<PowerControlCommand>();
|
||||
cmd->setPowerOn(turnOn);
|
||||
cmd->setTargetAddress(serial());
|
||||
PowerCommand()->setLastPowerCommandSuccess(CMD_PENDING);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HM_Abstract::resendPowerControlRequest(HoymilesRadio* radio)
|
||||
{
|
||||
return sendPowerControlRequest(radio, _powerState);
|
||||
}
|
||||
@ -11,9 +11,13 @@ public:
|
||||
bool sendSystemConfigParaRequest(HoymilesRadio* radio);
|
||||
bool sendActivePowerControlRequest(HoymilesRadio* radio, float limit, PowerLimitControlType type);
|
||||
bool resendActivePowerControlRequest(HoymilesRadio* radio);
|
||||
bool sendPowerControlRequest(HoymilesRadio* radio, bool turnOn);
|
||||
bool resendPowerControlRequest(HoymilesRadio* radio);
|
||||
|
||||
private:
|
||||
uint8_t _lastAlarmLogCnt = 0;
|
||||
float _activePowerControlLimit = 0;
|
||||
PowerLimitControlType _activePowerControlType = PowerLimitControlType::AbsolutNonPersistent;
|
||||
|
||||
bool _powerState = true;
|
||||
};
|
||||
@ -7,6 +7,7 @@ InverterAbstract::InverterAbstract(uint64_t serial)
|
||||
_serial.u64 = serial;
|
||||
_alarmLogParser.reset(new AlarmLogParser());
|
||||
_devInfoParser.reset(new DevInfoParser());
|
||||
_powerCommandParser.reset(new PowerCommandParser());
|
||||
_statisticsParser.reset(new StatisticsParser());
|
||||
_systemConfigParaParser.reset(new SystemConfigParaParser());
|
||||
}
|
||||
@ -64,6 +65,11 @@ DevInfoParser* InverterAbstract::DevInfo()
|
||||
return _devInfoParser.get();
|
||||
}
|
||||
|
||||
PowerCommandParser* InverterAbstract::PowerCommand()
|
||||
{
|
||||
return _powerCommandParser.get();
|
||||
}
|
||||
|
||||
StatisticsParser* InverterAbstract::Statistics()
|
||||
{
|
||||
return _statisticsParser.get();
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include "../commands/ActivePowerControlCommand.h"
|
||||
#include "../parser/AlarmLogParser.h"
|
||||
#include "../parser/DevInfoParser.h"
|
||||
#include "../parser/PowerCommandParser.h"
|
||||
#include "../parser/StatisticsParser.h"
|
||||
#include "../parser/SystemConfigParaParser.h"
|
||||
#include "HoymilesRadio.h"
|
||||
@ -51,9 +52,12 @@ public:
|
||||
virtual bool sendSystemConfigParaRequest(HoymilesRadio* radio) = 0;
|
||||
virtual bool sendActivePowerControlRequest(HoymilesRadio* radio, float limit, PowerLimitControlType type) = 0;
|
||||
virtual bool resendActivePowerControlRequest(HoymilesRadio* radio) = 0;
|
||||
virtual bool sendPowerControlRequest(HoymilesRadio* radio, bool turnOn) = 0;
|
||||
virtual bool resendPowerControlRequest(HoymilesRadio* radio) = 0;
|
||||
|
||||
AlarmLogParser* EventLog();
|
||||
DevInfoParser* DevInfo();
|
||||
PowerCommandParser* PowerCommand();
|
||||
StatisticsParser* Statistics();
|
||||
SystemConfigParaParser* SystemConfigPara();
|
||||
|
||||
@ -67,6 +71,7 @@ private:
|
||||
|
||||
std::unique_ptr<AlarmLogParser> _alarmLogParser;
|
||||
std::unique_ptr<DevInfoParser> _devInfoParser;
|
||||
std::unique_ptr<PowerCommandParser> _powerCommandParser;
|
||||
std::unique_ptr<StatisticsParser> _statisticsParser;
|
||||
std::unique_ptr<SystemConfigParaParser> _systemConfigParaParser;
|
||||
};
|
||||
@ -40,12 +40,12 @@ void AlarmLogParser::getLogEntry(uint8_t entryId, AlarmLogEntry_t* entry)
|
||||
|
||||
uint32_t wcode = (uint16_t)_payloadAlarmLog[entryStartOffset] << 8 | _payloadAlarmLog[entryStartOffset + 1];
|
||||
uint32_t startTimeOffset = 0;
|
||||
if ((wcode >> 13) & 0x01 == 1) {
|
||||
if (((wcode >> 13) & 0x01) == 1) {
|
||||
startTimeOffset = 12 * 60 * 60;
|
||||
}
|
||||
|
||||
uint32_t endTimeOffset = 0;
|
||||
if ((wcode >> 12) & 0x01 == 1) {
|
||||
if (((wcode >> 12) & 0x01) == 1) {
|
||||
endTimeOffset = 12 * 60 * 60;
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ void DevInfoParser::clearBufferSimple()
|
||||
void DevInfoParser::appendFragmentSimple(uint8_t offset, uint8_t* payload, uint8_t len)
|
||||
{
|
||||
if (offset + len > DEV_INFO_SIZE) {
|
||||
Serial.printf("FATAL: (%s, %d) dev info Sample packet too large for buffer\n", __FILE__, __LINE__);
|
||||
Serial.printf("FATAL: (%s, %d) dev info Simple packet too large for buffer\n", __FILE__, __LINE__);
|
||||
return;
|
||||
}
|
||||
memcpy(&_payloadDevInfoSimple[offset], payload, len);
|
||||
@ -44,14 +44,14 @@ void DevInfoParser::setLastUpdateAll(uint32_t lastUpdate)
|
||||
setLastUpdate(lastUpdate);
|
||||
}
|
||||
|
||||
uint32_t DevInfoParser::getLastUpdateSample()
|
||||
uint32_t DevInfoParser::getLastUpdateSimple()
|
||||
{
|
||||
return _lastUpdateSample;
|
||||
return _lastUpdateSimple;
|
||||
}
|
||||
|
||||
void DevInfoParser::setLastUpdateSample(uint32_t lastUpdate)
|
||||
void DevInfoParser::setLastUpdateSimple(uint32_t lastUpdate)
|
||||
{
|
||||
_lastUpdateSample = lastUpdate;
|
||||
_lastUpdateSimple = lastUpdate;
|
||||
setLastUpdate(lastUpdate);
|
||||
}
|
||||
|
||||
@ -90,9 +90,11 @@ uint32_t DevInfoParser::getHwPartNumber()
|
||||
return ((uint32_t)hwpn_h << 16) | ((uint32_t)hwpn_l);
|
||||
}
|
||||
|
||||
uint16_t DevInfoParser::getHwVersion()
|
||||
String DevInfoParser::getHwVersion()
|
||||
{
|
||||
return (((uint16_t)_payloadDevInfoSimple[6]) << 8) | _payloadDevInfoSimple[7];
|
||||
char buf[6];
|
||||
snprintf(buf, sizeof(buf), "%02X.%02X", _payloadDevInfoSimple[6], _payloadDevInfoSimple[7]);
|
||||
return String(buf);
|
||||
}
|
||||
|
||||
/* struct tm to seconds since Unix epoch */
|
||||
|
||||
@ -15,21 +15,21 @@ public:
|
||||
uint32_t getLastUpdateAll();
|
||||
void setLastUpdateAll(uint32_t lastUpdate);
|
||||
|
||||
uint32_t getLastUpdateSample();
|
||||
void setLastUpdateSample(uint32_t lastUpdate);
|
||||
uint32_t getLastUpdateSimple();
|
||||
void setLastUpdateSimple(uint32_t lastUpdate);
|
||||
|
||||
uint16_t getFwBuildVersion();
|
||||
time_t getFwBuildDateTime();
|
||||
uint16_t getFwBootloaderVersion();
|
||||
|
||||
uint32_t getHwPartNumber();
|
||||
uint16_t getHwVersion();
|
||||
String getHwVersion();
|
||||
|
||||
private:
|
||||
time_t timegm(struct tm* tm);
|
||||
|
||||
uint32_t _lastUpdateAll = 0;
|
||||
uint32_t _lastUpdateSample = 0;
|
||||
uint32_t _lastUpdateSimple = 0;
|
||||
|
||||
uint8_t _payloadDevInfoAll[DEV_INFO_SIZE] = {};
|
||||
uint8_t _devInfoAllLength = 0;
|
||||
|
||||
22
lib/Hoymiles/src/parser/PowerCommandParser.cpp
Normal file
22
lib/Hoymiles/src/parser/PowerCommandParser.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "PowerCommandParser.h"
|
||||
|
||||
void PowerCommandParser::setLastPowerCommandSuccess(LastCommandSuccess status)
|
||||
{
|
||||
_lastLimitCommandSuccess = status;
|
||||
}
|
||||
|
||||
LastCommandSuccess PowerCommandParser::getLastPowerCommandSuccess()
|
||||
{
|
||||
return _lastLimitCommandSuccess;
|
||||
}
|
||||
|
||||
uint32_t PowerCommandParser::getLastUpdateCommand()
|
||||
{
|
||||
return _lastUpdateCommand;
|
||||
}
|
||||
|
||||
void PowerCommandParser::setLastUpdateCommand(uint32_t lastUpdate)
|
||||
{
|
||||
_lastUpdateCommand = lastUpdate;
|
||||
setLastUpdate(lastUpdate);
|
||||
}
|
||||
16
lib/Hoymiles/src/parser/PowerCommandParser.h
Normal file
16
lib/Hoymiles/src/parser/PowerCommandParser.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include "Parser.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
class PowerCommandParser : public Parser {
|
||||
public:
|
||||
void setLastPowerCommandSuccess(LastCommandSuccess status);
|
||||
LastCommandSuccess getLastPowerCommandSuccess();
|
||||
uint32_t getLastUpdateCommand();
|
||||
void setLastUpdateCommand(uint32_t lastUpdate);
|
||||
|
||||
private:
|
||||
LastCommandSuccess _lastLimitCommandSuccess = CMD_OK; // Set to OK because we have to assume nothing is done at startup
|
||||
|
||||
uint32_t _lastUpdateCommand = 0;
|
||||
};
|
||||
@ -1,5 +1,28 @@
|
||||
#include "StatisticsParser.h"
|
||||
|
||||
static float calcYieldTotalCh0(StatisticsParser* iv, uint8_t arg0);
|
||||
static float calcYieldDayCh0(StatisticsParser* iv, uint8_t arg0);
|
||||
static float calcUdcCh(StatisticsParser* iv, uint8_t arg0);
|
||||
static float calcPowerDcCh0(StatisticsParser* iv, uint8_t arg0);
|
||||
static float calcEffiencyCh0(StatisticsParser* iv, uint8_t arg0);
|
||||
static float calcIrradiation(StatisticsParser* iv, uint8_t arg0);
|
||||
|
||||
using func_t = float(StatisticsParser*, uint8_t);
|
||||
|
||||
struct calcFunc_t {
|
||||
uint8_t funcId; // unique id
|
||||
func_t* func; // function pointer
|
||||
};
|
||||
|
||||
const calcFunc_t calcFunctions[] = {
|
||||
{ CALC_YT_CH0, &calcYieldTotalCh0 },
|
||||
{ CALC_YD_CH0, &calcYieldDayCh0 },
|
||||
{ CALC_UDC_CH, &calcUdcCh },
|
||||
{ CALC_PDC_CH0, &calcPowerDcCh0 },
|
||||
{ CALC_EFF_CH0, &calcEffiencyCh0 },
|
||||
{ CALC_IRR_CH, &calcIrradiation }
|
||||
};
|
||||
|
||||
void StatisticsParser::setByteAssignment(const byteAssign_t* byteAssignment, const uint8_t count)
|
||||
{
|
||||
_byteAssignment = byteAssignment;
|
||||
|
||||
@ -70,31 +70,6 @@ typedef struct {
|
||||
uint16_t div; // divisor / calc command
|
||||
} byteAssign_t;
|
||||
|
||||
// prototypes
|
||||
class StatisticsParser;
|
||||
static float calcYieldTotalCh0(StatisticsParser* iv, uint8_t arg0);
|
||||
static float calcYieldDayCh0(StatisticsParser* iv, uint8_t arg0);
|
||||
static float calcUdcCh(StatisticsParser* iv, uint8_t arg0);
|
||||
static float calcPowerDcCh0(StatisticsParser* iv, uint8_t arg0);
|
||||
static float calcEffiencyCh0(StatisticsParser* iv, uint8_t arg0);
|
||||
static float calcIrradiation(StatisticsParser* iv, uint8_t arg0);
|
||||
|
||||
using func_t = float(StatisticsParser*, uint8_t);
|
||||
|
||||
struct calcFunc_t {
|
||||
uint8_t funcId; // unique id
|
||||
func_t* func; // function pointer
|
||||
};
|
||||
|
||||
const calcFunc_t calcFunctions[] = {
|
||||
{ CALC_YT_CH0, &calcYieldTotalCh0 },
|
||||
{ CALC_YD_CH0, &calcYieldDayCh0 },
|
||||
{ CALC_UDC_CH, &calcUdcCh },
|
||||
{ CALC_PDC_CH0, &calcPowerDcCh0 },
|
||||
{ CALC_EFF_CH0, &calcEffiencyCh0 },
|
||||
{ CALC_IRR_CH, &calcIrradiation }
|
||||
};
|
||||
|
||||
class StatisticsParser : public Parser {
|
||||
public:
|
||||
void clearBuffer();
|
||||
|
||||
@ -13,16 +13,17 @@ default_envs = generic
|
||||
|
||||
[env]
|
||||
framework = arduino
|
||||
platform = espressif32@>=5
|
||||
platform = espressif32@>=5.2.0
|
||||
|
||||
build_flags =
|
||||
-D=${PIOENV}
|
||||
-DCOMPONENT_EMBED_FILES=webapp_dist/index.html.gz:webapp_dist/zones.json.gz:webapp_dist/favicon.ico:webapp_dist/js/app.js.gz
|
||||
-Wall
|
||||
|
||||
lib_deps =
|
||||
https://github.com/yubox-node-org/ESPAsyncWebServer
|
||||
bblanchon/ArduinoJson @ ^6.19.4
|
||||
https://github.com/bertmelis/espMqttClient.git#v1.3.1
|
||||
https://github.com/bertmelis/espMqttClient.git#v1.3.2
|
||||
nrf24/RF24 @ ^1.4.5
|
||||
|
||||
extra_scripts =
|
||||
|
||||
@ -74,7 +74,7 @@ void MqttHassPublishingClass::publishField(std::shared_ptr<InverterAbstract> inv
|
||||
}
|
||||
|
||||
char serial[sizeof(uint64_t) * 8 + 1];
|
||||
snprintf(serial, sizeof(serial), "%0lx%08lx",
|
||||
snprintf(serial, sizeof(serial), "%0x%08x",
|
||||
((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)),
|
||||
((uint32_t)(inv->serial() & 0xFFFFFFFF)));
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ void MqttPublishingClass::loop()
|
||||
auto inv = Hoymiles.getInverterByPos(i);
|
||||
|
||||
char buffer[sizeof(uint64_t) * 8 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%0lx%08lx",
|
||||
snprintf(buffer, sizeof(buffer), "%0x%08x",
|
||||
((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)),
|
||||
((uint32_t)(inv->serial() & 0xFFFFFFFF)));
|
||||
String subtopic = String(buffer);
|
||||
@ -59,7 +59,7 @@ void MqttPublishingClass::loop()
|
||||
MqttSettings.publish(subtopic + "/device/hwpartnumber", String(inv->DevInfo()->getHwPartNumber()));
|
||||
|
||||
// Hardware version
|
||||
MqttSettings.publish(subtopic + "/device/hwversion", String(inv->DevInfo()->getHwVersion()));
|
||||
MqttSettings.publish(subtopic + "/device/hwversion", inv->DevInfo()->getHwVersion());
|
||||
}
|
||||
|
||||
if (inv->SystemConfigPara()->getLastUpdate() > 0) {
|
||||
@ -106,7 +106,7 @@ String MqttPublishingClass::getTopic(std::shared_ptr<InverterAbstract> inv, uint
|
||||
}
|
||||
|
||||
char buffer[sizeof(uint64_t) * 8 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%0lx%08lx",
|
||||
snprintf(buffer, sizeof(buffer), "%0x%08x",
|
||||
((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)),
|
||||
((uint32_t)(inv->serial() & 0xFFFFFFFF)));
|
||||
String invSerial = String(buffer);
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#define TOPIC_SUB_LIMIT_PERSISTENT_ABSOLUTE "limit_persistent_absolute"
|
||||
#define TOPIC_SUB_LIMIT_NONPERSISTENT_RELATIVE "limit_nonpersistent_relative"
|
||||
#define TOPIC_SUB_LIMIT_NONPERSISTENT_ABSOLUTE "limit_nonpersistent_absolute"
|
||||
#define TOPIC_SUB_POWER "power"
|
||||
|
||||
MqttSettingsClass::MqttSettingsClass()
|
||||
{
|
||||
@ -30,6 +31,8 @@ void MqttSettingsClass::NetworkEvent(network_event event)
|
||||
Serial.println(F("Network lost connection"));
|
||||
mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,6 +47,7 @@ void MqttSettingsClass::onMqttConnect(bool sessionPresent)
|
||||
mqttClient->subscribe(String(topic + "+/cmd/" + TOPIC_SUB_LIMIT_PERSISTENT_ABSOLUTE).c_str(), 0);
|
||||
mqttClient->subscribe(String(topic + "+/cmd/" + TOPIC_SUB_LIMIT_NONPERSISTENT_RELATIVE).c_str(), 0);
|
||||
mqttClient->subscribe(String(topic + "+/cmd/" + TOPIC_SUB_LIMIT_NONPERSISTENT_ABSOLUTE).c_str(), 0);
|
||||
mqttClient->subscribe(String(topic + "+/cmd/" + TOPIC_SUB_POWER).c_str(), 0);
|
||||
}
|
||||
|
||||
void MqttSettingsClass::onMqttDisconnect(espMqttClientTypes::DisconnectReason reason)
|
||||
@ -118,38 +122,43 @@ void MqttSettingsClass::onMqttMessage(const espMqttClientTypes::MessagePropertie
|
||||
char* strlimit = new char[len + 1];
|
||||
memcpy(strlimit, payload, len);
|
||||
strlimit[len] = '\0';
|
||||
uint32_t limit = strtol(strlimit, NULL, 10);
|
||||
uint32_t payload_val = strtol(strlimit, NULL, 10);
|
||||
delete[] strlimit;
|
||||
|
||||
if (!strcmp(setting, TOPIC_SUB_LIMIT_PERSISTENT_RELATIVE)) {
|
||||
// Set inverter limit relative persistent
|
||||
limit = min<uint32_t>(100, limit);
|
||||
Serial.printf("Limit Persistent: %d %%\n", limit);
|
||||
inv->sendActivePowerControlRequest(Hoymiles.getRadio(), limit, PowerLimitControlType::RelativPersistent);
|
||||
payload_val = min<uint32_t>(100, payload_val);
|
||||
Serial.printf("Limit Persistent: %d %%\n", payload_val);
|
||||
inv->sendActivePowerControlRequest(Hoymiles.getRadio(), payload_val, PowerLimitControlType::RelativPersistent);
|
||||
|
||||
} else if (!strcmp(setting, TOPIC_SUB_LIMIT_PERSISTENT_ABSOLUTE)) {
|
||||
// Set inverter limit absolute persistent
|
||||
Serial.printf("Limit Persistent: %d W\n", limit);
|
||||
inv->sendActivePowerControlRequest(Hoymiles.getRadio(), limit, PowerLimitControlType::AbsolutPersistent);
|
||||
Serial.printf("Limit Persistent: %d W\n", payload_val);
|
||||
inv->sendActivePowerControlRequest(Hoymiles.getRadio(), payload_val, PowerLimitControlType::AbsolutPersistent);
|
||||
|
||||
} else if (!strcmp(setting, TOPIC_SUB_LIMIT_NONPERSISTENT_RELATIVE)) {
|
||||
// Set inverter limit relative non persistent
|
||||
limit = min<uint32_t>(100, limit);
|
||||
Serial.printf("Limit Non-Persistent: %d %%\n", limit);
|
||||
payload_val = min<uint32_t>(100, payload_val);
|
||||
Serial.printf("Limit Non-Persistent: %d %%\n", payload_val);
|
||||
if (!properties.retain) {
|
||||
inv->sendActivePowerControlRequest(Hoymiles.getRadio(), limit, PowerLimitControlType::RelativNonPersistent);
|
||||
inv->sendActivePowerControlRequest(Hoymiles.getRadio(), payload_val, PowerLimitControlType::RelativNonPersistent);
|
||||
} else {
|
||||
Serial.println("Ignored because retained");
|
||||
}
|
||||
|
||||
} else if (!strcmp(setting, TOPIC_SUB_LIMIT_NONPERSISTENT_ABSOLUTE)) {
|
||||
// Set inverter limit absolute non persistent
|
||||
Serial.printf("Limit Non-Persistent: %d W\n", limit);
|
||||
Serial.printf("Limit Non-Persistent: %d W\n", payload_val);
|
||||
if (!properties.retain) {
|
||||
inv->sendActivePowerControlRequest(Hoymiles.getRadio(), limit, PowerLimitControlType::AbsolutNonPersistent);
|
||||
inv->sendActivePowerControlRequest(Hoymiles.getRadio(), payload_val, PowerLimitControlType::AbsolutNonPersistent);
|
||||
} else {
|
||||
Serial.println("Ignored because retained");
|
||||
}
|
||||
|
||||
} else if(!strcmp(setting, TOPIC_SUB_POWER)) {
|
||||
// Turn inverter on or off
|
||||
Serial.printf("Set inverter power to: %d\n", payload_val);
|
||||
inv->sendPowerControlRequest(Hoymiles.getRadio(), payload_val > 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -27,6 +27,7 @@ void WebApiClass::init()
|
||||
_webApiMqtt.init(&_server);
|
||||
_webApiNetwork.init(&_server);
|
||||
_webApiNtp.init(&_server);
|
||||
_webApiPower.init(&_server);
|
||||
_webApiSysstatus.init(&_server);
|
||||
_webApiWebapp.init(&_server);
|
||||
_webApiWsLive.init(&_server);
|
||||
@ -48,6 +49,7 @@ void WebApiClass::loop()
|
||||
_webApiMqtt.loop();
|
||||
_webApiNetwork.loop();
|
||||
_webApiNtp.loop();
|
||||
_webApiPower.loop();
|
||||
_webApiSysstatus.loop();
|
||||
_webApiWebapp.loop();
|
||||
_webApiWsLive.loop();
|
||||
|
||||
@ -31,11 +31,12 @@ void WebApiDevInfoClass::onDevInfoStatus(AsyncWebServerRequest* request)
|
||||
|
||||
// Inverter Serial is read as HEX
|
||||
char buffer[sizeof(uint64_t) * 8 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%0lx%08lx",
|
||||
snprintf(buffer, sizeof(buffer), "%0x%08x",
|
||||
((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)),
|
||||
((uint32_t)(inv->serial() & 0xFFFFFFFF)));
|
||||
|
||||
JsonObject devInfoObj = root[buffer].createNestedObject();
|
||||
devInfoObj[F("valid_data")] = inv->DevInfo()->getLastUpdate() > 0;
|
||||
devInfoObj[F("fw_bootloader_version")] = inv->DevInfo()->getFwBootloaderVersion();
|
||||
devInfoObj[F("fw_build_version")] = inv->DevInfo()->getFwBuildVersion();
|
||||
devInfoObj[F("hw_part_number")] = inv->DevInfo()->getHwPartNumber();
|
||||
|
||||
@ -30,7 +30,7 @@ void WebApiDtuClass::onDtuAdminGet(AsyncWebServerRequest* request)
|
||||
|
||||
// DTU Serial is read as HEX
|
||||
char buffer[sizeof(uint64_t) * 8 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%0lx%08lx",
|
||||
snprintf(buffer, sizeof(buffer), "%0x%08x",
|
||||
((uint32_t)((config.Dtu_Serial >> 32) & 0xFFFFFFFF)),
|
||||
((uint32_t)(config.Dtu_Serial & 0xFFFFFFFF)));
|
||||
root[F("dtu_serial")] = buffer;
|
||||
|
||||
@ -36,7 +36,7 @@ void WebApiEventlogClass::onEventlogStatus(AsyncWebServerRequest* request)
|
||||
if (inv != nullptr) {
|
||||
// Inverter Serial is read as HEX
|
||||
char buffer[sizeof(uint64_t) * 8 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%0lx%08lx",
|
||||
snprintf(buffer, sizeof(buffer), "%0x%08x",
|
||||
((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)),
|
||||
((uint32_t)(inv->serial() & 0xFFFFFFFF)));
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ void WebApiInverterClass::onInverterList(AsyncWebServerRequest* request)
|
||||
|
||||
// Inverter Serial is read as HEX
|
||||
char buffer[sizeof(uint64_t) * 8 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%0lx%08lx",
|
||||
snprintf(buffer, sizeof(buffer), "%0x%08x",
|
||||
((uint32_t)((config.Inverter[i].Serial >> 32) & 0xFFFFFFFF)),
|
||||
((uint32_t)(config.Inverter[i].Serial & 0xFFFFFFFF)));
|
||||
obj[F("serial")] = buffer;
|
||||
@ -210,11 +210,7 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
||||
}
|
||||
|
||||
JsonArray maxPowerArray = root[F("max_power")].as<JsonArray>();
|
||||
uint8_t arrayCount = 0;
|
||||
for (JsonVariant maxPower : maxPowerArray) {
|
||||
arrayCount++;
|
||||
}
|
||||
if (arrayCount != INV_MAX_CHAN_COUNT) {
|
||||
if (maxPowerArray.size() != INV_MAX_CHAN_COUNT) {
|
||||
retMsg[F("message")] = F("Invalid amount of max channel setting given!");
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -230,7 +226,7 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
||||
inverter.Serial = new_serial;
|
||||
strncpy(inverter.Name, root[F("name")].as<String>().c_str(), INV_MAX_NAME_STRLEN);
|
||||
|
||||
arrayCount = 0;
|
||||
uint8_t arrayCount = 0;
|
||||
for (JsonVariant maxPower : maxPowerArray) {
|
||||
inverter.MaxChannelPower[arrayCount] = maxPower.as<uint16_t>();
|
||||
arrayCount++;
|
||||
@ -319,7 +315,7 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
|
||||
Hoymiles.removeInverterBySerial(inverter.Serial);
|
||||
|
||||
inverter.Serial = 0;
|
||||
strncpy(inverter.Name, "", 0);
|
||||
strncpy(inverter.Name, "", sizeof(inverter.Name));
|
||||
Configuration.write();
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
|
||||
@ -31,7 +31,7 @@ void WebApiLimitClass::onLimitStatus(AsyncWebServerRequest* request)
|
||||
|
||||
// Inverter Serial is read as HEX
|
||||
char buffer[sizeof(uint64_t) * 8 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%0lx%08lx",
|
||||
snprintf(buffer, sizeof(buffer), "%0x%08x",
|
||||
((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)),
|
||||
((uint32_t)(inv->serial() & 0xFFFFFFFF)));
|
||||
|
||||
|
||||
121
src/WebApi_power.cpp
Normal file
121
src/WebApi_power.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2022 Thomas Basler and others
|
||||
*/
|
||||
#include "WebApi_power.h"
|
||||
#include "ArduinoJson.h"
|
||||
#include "AsyncJson.h"
|
||||
#include "Hoymiles.h"
|
||||
|
||||
void WebApiPowerClass::init(AsyncWebServer* server)
|
||||
{
|
||||
using std::placeholders::_1;
|
||||
|
||||
_server = server;
|
||||
|
||||
_server->on("/api/power/status", HTTP_GET, std::bind(&WebApiPowerClass::onPowerStatus, this, _1));
|
||||
_server->on("/api/power/config", HTTP_POST, std::bind(&WebApiPowerClass::onPowerPost, this, _1));
|
||||
}
|
||||
|
||||
void WebApiPowerClass::loop()
|
||||
{
|
||||
}
|
||||
|
||||
void WebApiPowerClass::onPowerStatus(AsyncWebServerRequest* request)
|
||||
{
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) {
|
||||
auto inv = Hoymiles.getInverterByPos(i);
|
||||
|
||||
// Inverter Serial is read as HEX
|
||||
char buffer[sizeof(uint64_t) * 8 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%0x%08x",
|
||||
((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)),
|
||||
((uint32_t)(inv->serial() & 0xFFFFFFFF)));
|
||||
|
||||
LastCommandSuccess status = inv->PowerCommand()->getLastPowerCommandSuccess();
|
||||
String limitStatus = "Unknown";
|
||||
if (status == LastCommandSuccess::CMD_OK) {
|
||||
limitStatus = "Ok";
|
||||
}
|
||||
else if (status == LastCommandSuccess::CMD_NOK) {
|
||||
limitStatus = "Failure";
|
||||
}
|
||||
else if (status == LastCommandSuccess::CMD_PENDING) {
|
||||
limitStatus = "Pending";
|
||||
}
|
||||
root[buffer]["power_set_status"] = limitStatus;
|
||||
}
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
|
||||
{
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
DynamicJsonDocument root(1024);
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(root.containsKey("serial")
|
||||
&& root.containsKey("power"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("serial")].as<uint64_t>() == 0) {
|
||||
retMsg[F("message")] = F("Serial must be a number > 0!");
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t serial = strtoll(root[F("serial")].as<String>().c_str(), NULL, 16);
|
||||
uint16_t power = root[F("power")].as<bool>();
|
||||
|
||||
auto inv = Hoymiles.getInverterBySerial(serial);
|
||||
if (inv == nullptr) {
|
||||
retMsg[F("message")] = F("Invalid inverter specified!");
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
inv->sendPowerControlRequest(Hoymiles.getRadio(), power);
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Settings saved!");
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
||||
@ -59,7 +59,7 @@ void WebApiSysstatusClass::onSystemStatus(AsyncWebServerRequest* request)
|
||||
|
||||
char version[16];
|
||||
snprintf(version, sizeof(version), "%d.%d.%d", CONFIG_VERSION >> 24 & 0xff, CONFIG_VERSION >> 16 & 0xff, CONFIG_VERSION >> 8 & 0xff);
|
||||
root[F("firmware_version")] = version;
|
||||
root[F("config_version")] = version;
|
||||
root[F("git_hash")] = AUTO_GIT_HASH;
|
||||
|
||||
root[F("uptime")] = esp_timer_get_time() / 1000000;
|
||||
|
||||
@ -78,7 +78,7 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
|
||||
auto inv = Hoymiles.getInverterByPos(i);
|
||||
|
||||
char buffer[sizeof(uint64_t) * 8 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%0lx%08lx",
|
||||
snprintf(buffer, sizeof(buffer), "%0x%08x",
|
||||
((uint32_t)((inv->serial() >> 32) & 0xFFFFFFFF)),
|
||||
((uint32_t)(inv->serial() & 0xFFFFFFFF)));
|
||||
|
||||
|
||||
@ -9,21 +9,21 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"bootstrap": "^5.2.1",
|
||||
"bootstrap": "^5.2.2",
|
||||
"bootstrap-icons-vue": "^1.8.1",
|
||||
"core-js": "^3.25.3",
|
||||
"core-js": "^3.25.5",
|
||||
"spark-md5": "^3.0.2",
|
||||
"vue": "^3.2.39",
|
||||
"vue": "^3.2.40",
|
||||
"vue-class-component": "^8.0.0-0",
|
||||
"vue-router": "^4.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.19.1",
|
||||
"@babel/core": "^7.19.3",
|
||||
"@babel/eslint-parser": "^7.19.1",
|
||||
"@types/bootstrap": "^5.2.4",
|
||||
"@types/node": "^18.7.21",
|
||||
"@types/bootstrap": "^5.2.5",
|
||||
"@types/node": "^18.8.2",
|
||||
"@types/spark-md5": "^3.0.2",
|
||||
"@typescript-eslint/parser": "^5.37.0",
|
||||
"@typescript-eslint/parser": "^5.38.1",
|
||||
"@vue/cli-plugin-babel": "~5.0.8",
|
||||
"@vue/cli-plugin-eslint": "~5.0.8",
|
||||
"@vue/cli-plugin-router": "^5.0.6",
|
||||
@ -31,8 +31,8 @@
|
||||
"@vue/cli-service": "~5.0.8",
|
||||
"@vue/eslint-config-typescript": "^11.0.2",
|
||||
"eslint": "^8.24.0",
|
||||
"eslint-plugin-vue": "^9.5.1",
|
||||
"typescript": "^4.8.3",
|
||||
"eslint-plugin-vue": "^9.6.0",
|
||||
"typescript": "^4.8.4",
|
||||
"vue-cli-plugin-compression": "~2.0.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
|
||||
@ -52,6 +52,14 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="btn-group me-2" role="group">
|
||||
<button type="button" class="btn btn-sm btn-danger"
|
||||
@click="onShowPowerSettings(inverter.serial)" title="Turn Inverter on/off">
|
||||
<BIconPower style="font-size:24px;" />
|
||||
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="btn-group me-2" role="group">
|
||||
<button type="button" class="btn btn-sm btn-info"
|
||||
@click="onShowDevInfo(inverter.serial)" title="Show Inverter Info">
|
||||
@ -232,6 +240,59 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="powerSettingView" ref="powerSettingView" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Power Settings</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<BootstrapAlert v-model="showAlertPower" :variant="alertTypePower">
|
||||
{{ alertMessagePower }}
|
||||
</BootstrapAlert>
|
||||
<div class="text-center" v-if="powerSettingLoading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!powerSettingLoading">
|
||||
<div class="row mb-3 align-items-center">
|
||||
<label for="inputLastPowerSet" class="col col-form-label">Last Power Set
|
||||
Status:</label>
|
||||
<div class="col">
|
||||
<span class="badge" :class="{
|
||||
'bg-danger': successCommandPower == 'Failure',
|
||||
'bg-warning': successCommandPower == 'Pending',
|
||||
'bg-success': successCommandPower == 'Ok',
|
||||
'bg-secondary': successCommandPower == 'Unknown',
|
||||
}">
|
||||
{{ successCommandPower }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 col-6 mx-auto">
|
||||
<button type="button" class="btn btn-success" @click="onSetPowerSettings(true)">
|
||||
<BIconToggleOn class="fs-4" /> Turn On
|
||||
</button>
|
||||
<button type="button" class="btn btn-danger" @click="onSetPowerSettings(false)">
|
||||
<BIconToggleOff class="fs-4" /> Turn Off
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -292,6 +353,14 @@ export default defineComponent({
|
||||
alertMessageLimit: "",
|
||||
alertTypeLimit: "info",
|
||||
showAlertLimit: false,
|
||||
|
||||
powerSettingView: {} as bootstrap.Modal,
|
||||
powerSettingSerial: 0,
|
||||
powerSettingLoading: true,
|
||||
alertMessagePower: "",
|
||||
alertTypePower: "info",
|
||||
showAlertPower: false,
|
||||
successCommandPower: "",
|
||||
};
|
||||
},
|
||||
created() {
|
||||
@ -303,8 +372,10 @@ export default defineComponent({
|
||||
this.eventLogView = new bootstrap.Modal('#eventView');
|
||||
this.devInfoView = new bootstrap.Modal('#devInfoView');
|
||||
this.limitSettingView = new bootstrap.Modal('#limitSettingView');
|
||||
this.powerSettingView = new bootstrap.Modal('#powerSettingView');
|
||||
|
||||
(this.$refs.limitSettingView as HTMLElement).addEventListener("hide.bs.modal", this.onHideLimitSettings);
|
||||
(this.$refs.powerSettingView as HTMLElement).addEventListener("hide.bs.modal", this.onHidePowerSettings);
|
||||
},
|
||||
unmounted() {
|
||||
this.closeSocket();
|
||||
@ -483,6 +554,57 @@ export default defineComponent({
|
||||
}
|
||||
this.targetLimitType = type;
|
||||
},
|
||||
|
||||
onShowPowerSettings(serial: number) {
|
||||
this.powerSettingLoading = true;
|
||||
fetch("/api/power/status")
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
this.successCommandPower = data[serial].power_set_status;
|
||||
this.powerSettingSerial = serial;
|
||||
this.powerSettingLoading = false;
|
||||
});
|
||||
this.powerSettingView.show();
|
||||
},
|
||||
|
||||
onHidePowerSettings() {
|
||||
this.powerSettingSerial = 0;
|
||||
this.showAlertPower = false;
|
||||
},
|
||||
|
||||
onSetPowerSettings(turnOn: boolean) {
|
||||
const data = {
|
||||
serial: this.powerSettingSerial,
|
||||
power: turnOn,
|
||||
};
|
||||
const formData = new FormData();
|
||||
formData.append("data", JSON.stringify(data));
|
||||
|
||||
console.log(data);
|
||||
|
||||
fetch("/api/power/config", {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
})
|
||||
.then(function (response) {
|
||||
if (response.status != 200) {
|
||||
throw response.status;
|
||||
} else {
|
||||
return response.json();
|
||||
}
|
||||
})
|
||||
.then(
|
||||
(response) => {
|
||||
if (response.type == "success") {
|
||||
this.powerSettingView.hide();
|
||||
} else {
|
||||
this.alertMessagePower = response.message;
|
||||
this.alertTypePower = response.type;
|
||||
this.showAlertPower = true;
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -45,12 +45,15 @@ export default defineComponent({
|
||||
// FirmwareInfo
|
||||
hostname: "",
|
||||
sdkversion: "",
|
||||
firmware_version: "",
|
||||
config_version: "",
|
||||
git_hash: "",
|
||||
resetreason_0: "",
|
||||
resetreason_1: "",
|
||||
cfgsavecount: 0,
|
||||
uptime: 0,
|
||||
update_text: "",
|
||||
update_url: "",
|
||||
update_status: "",
|
||||
// MemoryInfo
|
||||
heap_total: 0,
|
||||
heap_used: 0,
|
||||
@ -72,8 +75,35 @@ export default defineComponent({
|
||||
.then((data) => {
|
||||
this.systemDataList = data;
|
||||
this.dataLoading = false;
|
||||
this.getUpdateInfo();
|
||||
})
|
||||
},
|
||||
getUpdateInfo() {
|
||||
const fetchUrl = "https://api.github.com/repos/tbnobody/OpenDTU/compare/"
|
||||
+ this.systemDataList.git_hash?.substring(1) + "...HEAD";
|
||||
|
||||
fetch(fetchUrl)
|
||||
.then((response) => {
|
||||
if (response.ok) {
|
||||
return response.json()
|
||||
}
|
||||
throw new Error('Error fetching version information');
|
||||
})
|
||||
.then((data) => {
|
||||
if (data.total_commits > 0) {
|
||||
this.systemDataList.update_text = "New version available! Show changes!"
|
||||
this.systemDataList.update_status = "text-bg-danger";
|
||||
this.systemDataList.update_url = data.html_url;
|
||||
} else {
|
||||
this.systemDataList.update_text = "Up to date!"
|
||||
this.systemDataList.update_status = "text-bg-success";
|
||||
}
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
this.systemDataList.update_text = error.message;
|
||||
this.systemDataList.update_status = "text-bg-secondary";
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
<template>
|
||||
<table class="table table-hover">
|
||||
<BootstrapAlert :show="!devInfoList.valid_data">
|
||||
<h4 class="alert-heading">
|
||||
<BIconInfoSquare class="fs-2" /> No Information available
|
||||
</h4>Did not receive any valid data from the inverter till now. Still trying...
|
||||
</BootstrapAlert>
|
||||
<table v-if="devInfoList.valid_data" class="table table-hover">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Bootloader Version</td>
|
||||
@ -27,8 +32,10 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BootstrapAlert from '@/components/partials/BootstrapAlert.vue';
|
||||
|
||||
declare interface DevInfoData {
|
||||
valid_data: boolean,
|
||||
fw_bootloader_version: number,
|
||||
fw_build_version: number,
|
||||
fw_build_datetime: Date,
|
||||
@ -37,6 +44,9 @@ declare interface DevInfoData {
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BootstrapAlert,
|
||||
},
|
||||
props: {
|
||||
devInfoList: { type: Object as () => DevInfoData, required: true },
|
||||
},
|
||||
|
||||
@ -16,12 +16,18 @@
|
||||
<td>{{ sdkversion }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Firmware Version</th>
|
||||
<td>{{ firmware_version }}</td>
|
||||
<th>Config Version</th>
|
||||
<td>{{ config_version }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Git Hash</th>
|
||||
<td><a :href="'https://github.com/tbnobody/OpenDTU/commits/' + git_hash?.substring(1)" target="_blank">{{ git_hash?.substring(1) }}</a></td>
|
||||
<th>Firmware Version / Git Hash</th>
|
||||
<td><a :href="'https://github.com/tbnobody/OpenDTU/commits/' + git_hash?.substring(1)"
|
||||
target="_blank">{{ git_hash?.substring(1) }}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Firmware Update</th>
|
||||
<td><a :href="update_url" target="_blank"><span class="badge" :class="update_status">{{
|
||||
update_text }}</span></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Reset Reason CPU 0</th>
|
||||
@ -53,12 +59,15 @@ export default defineComponent({
|
||||
props: {
|
||||
hostname: String,
|
||||
sdkversion: String,
|
||||
firmware_version: String,
|
||||
config_version: String,
|
||||
git_hash: String,
|
||||
resetreason_0: String,
|
||||
resetreason_1: String,
|
||||
cfgsavecount: { type: Number, required: true },
|
||||
uptime: { type: Number, required: true },
|
||||
update_text: String,
|
||||
update_url: String,
|
||||
update_status: String,
|
||||
},
|
||||
computed: {
|
||||
timeInHours() {
|
||||
|
||||
321
webapp/yarn.lock
321
webapp/yarn.lock
@ -36,10 +36,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d"
|
||||
integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==
|
||||
|
||||
"@babel/compat-data@^7.19.1":
|
||||
version "7.19.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.1.tgz#72d647b4ff6a4f82878d184613353af1dd0290f9"
|
||||
integrity sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg==
|
||||
"@babel/compat-data@^7.19.3":
|
||||
version "7.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.3.tgz#707b939793f867f5a73b2666e6d9a3396eb03151"
|
||||
integrity sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==
|
||||
|
||||
"@babel/core@^7.12.16":
|
||||
version "7.18.10"
|
||||
@ -62,21 +62,21 @@
|
||||
json5 "^2.2.1"
|
||||
semver "^6.3.0"
|
||||
|
||||
"@babel/core@^7.19.1":
|
||||
version "7.19.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.1.tgz#c8fa615c5e88e272564ace3d42fbc8b17bfeb22b"
|
||||
integrity sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw==
|
||||
"@babel/core@^7.19.3":
|
||||
version "7.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.3.tgz#2519f62a51458f43b682d61583c3810e7dcee64c"
|
||||
integrity sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==
|
||||
dependencies:
|
||||
"@ampproject/remapping" "^2.1.0"
|
||||
"@babel/code-frame" "^7.18.6"
|
||||
"@babel/generator" "^7.19.0"
|
||||
"@babel/helper-compilation-targets" "^7.19.1"
|
||||
"@babel/generator" "^7.19.3"
|
||||
"@babel/helper-compilation-targets" "^7.19.3"
|
||||
"@babel/helper-module-transforms" "^7.19.0"
|
||||
"@babel/helpers" "^7.19.0"
|
||||
"@babel/parser" "^7.19.1"
|
||||
"@babel/parser" "^7.19.3"
|
||||
"@babel/template" "^7.18.10"
|
||||
"@babel/traverse" "^7.19.1"
|
||||
"@babel/types" "^7.19.0"
|
||||
"@babel/traverse" "^7.19.3"
|
||||
"@babel/types" "^7.19.3"
|
||||
convert-source-map "^1.7.0"
|
||||
debug "^4.1.0"
|
||||
gensync "^1.0.0-beta.2"
|
||||
@ -110,6 +110,15 @@
|
||||
"@jridgewell/gen-mapping" "^0.3.2"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/generator@^7.19.3":
|
||||
version "7.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.3.tgz#d7f4d1300485b4547cb6f94b27d10d237b42bf59"
|
||||
integrity sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==
|
||||
dependencies:
|
||||
"@babel/types" "^7.19.3"
|
||||
"@jridgewell/gen-mapping" "^0.3.2"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
"@babel/helper-annotate-as-pure@^7.16.7":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862"
|
||||
@ -135,12 +144,12 @@
|
||||
browserslist "^4.20.2"
|
||||
semver "^6.3.0"
|
||||
|
||||
"@babel/helper-compilation-targets@^7.19.1":
|
||||
version "7.19.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz#7f630911d83b408b76fe584831c98e5395d7a17c"
|
||||
integrity sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg==
|
||||
"@babel/helper-compilation-targets@^7.19.3":
|
||||
version "7.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz#a10a04588125675d7c7ae299af86fa1b2ee038ca"
|
||||
integrity sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==
|
||||
dependencies:
|
||||
"@babel/compat-data" "^7.19.1"
|
||||
"@babel/compat-data" "^7.19.3"
|
||||
"@babel/helper-validator-option" "^7.18.6"
|
||||
browserslist "^4.21.3"
|
||||
semver "^6.3.0"
|
||||
@ -366,6 +375,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076"
|
||||
integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.19.1":
|
||||
version "7.19.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
|
||||
integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
|
||||
|
||||
"@babel/helper-validator-option@^7.16.7":
|
||||
version "7.16.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23"
|
||||
@ -423,10 +437,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.0.tgz#497fcafb1d5b61376959c1c338745ef0577aa02c"
|
||||
integrity sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==
|
||||
|
||||
"@babel/parser@^7.19.1":
|
||||
version "7.19.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.1.tgz#6f6d6c2e621aad19a92544cc217ed13f1aac5b4c"
|
||||
integrity sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==
|
||||
"@babel/parser@^7.19.3":
|
||||
version "7.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.3.tgz#8dd36d17c53ff347f9e55c328710321b49479a9a"
|
||||
integrity sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==
|
||||
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.17.12":
|
||||
version "7.17.12"
|
||||
@ -1107,19 +1121,19 @@
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
|
||||
"@babel/traverse@^7.19.1":
|
||||
version "7.19.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.1.tgz#0fafe100a8c2a603b4718b1d9bf2568d1d193347"
|
||||
integrity sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==
|
||||
"@babel/traverse@^7.19.3":
|
||||
version "7.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.3.tgz#3a3c5348d4988ba60884e8494b0592b2f15a04b4"
|
||||
integrity sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.18.6"
|
||||
"@babel/generator" "^7.19.0"
|
||||
"@babel/generator" "^7.19.3"
|
||||
"@babel/helper-environment-visitor" "^7.18.9"
|
||||
"@babel/helper-function-name" "^7.19.0"
|
||||
"@babel/helper-hoist-variables" "^7.18.6"
|
||||
"@babel/helper-split-export-declaration" "^7.18.6"
|
||||
"@babel/parser" "^7.19.1"
|
||||
"@babel/types" "^7.19.0"
|
||||
"@babel/parser" "^7.19.3"
|
||||
"@babel/types" "^7.19.3"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
|
||||
@ -1141,6 +1155,15 @@
|
||||
"@babel/helper-validator-identifier" "^7.18.6"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.19.3":
|
||||
version "7.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.3.tgz#fc420e6bbe54880bce6779ffaf315f5e43ec9624"
|
||||
integrity sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.18.10"
|
||||
"@babel/helper-validator-identifier" "^7.19.1"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@eslint/eslintrc@^1.3.2":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.2.tgz#58b69582f3b7271d8fa67fe5251767a5b38ea356"
|
||||
@ -1344,10 +1367,10 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/bootstrap@^5.2.4":
|
||||
version "5.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/bootstrap/-/bootstrap-5.2.4.tgz#7f4f4af8e22af8247385549bd2f687088d00d2d3"
|
||||
integrity sha512-jGNB81zuDHu1DPvBV7Ox3Z3eyzdWPNguYwrt0j7X90VExA8H7c6qxJh0cz5j3xp0XvSy1TYaP2pkyXCHeo8CaA==
|
||||
"@types/bootstrap@^5.2.5":
|
||||
version "5.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/bootstrap/-/bootstrap-5.2.5.tgz#0bb5dea7720611b2bb7ba16bd8a64fafd86fb658"
|
||||
integrity sha512-VnalUJ3E/oaV3DYrauEc/sSPpaEPxTV09twSEzY4KFRvyuGlrZUSqG95XZ6ReAi0YMZIs7rXxdngDK2X1YONQA==
|
||||
dependencies:
|
||||
"@popperjs/core" "^2.9.2"
|
||||
|
||||
@ -1446,10 +1469,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.4.tgz#fd26723a8a3f8f46729812a7f9b4fc2d1608ed39"
|
||||
integrity sha512-I4BD3L+6AWiUobfxZ49DlU43gtI+FTHSv9pE2Zekg6KjMpre4ByusaljW3vYSLJrvQ1ck1hUaeVu8HVlY3vzHg==
|
||||
|
||||
"@types/node@^18.7.21":
|
||||
version "18.7.22"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.22.tgz#76f7401362ad63d9d7eefa7dcdfa5fcd9baddff3"
|
||||
integrity sha512-TsmoXYd4zrkkKjJB0URF/mTIKPl+kVcbqClB2F/ykU7vil1BfWZVndOnpEIozPv4fURD28gyPFeIkW2G+KXOvw==
|
||||
"@types/node@^18.8.2":
|
||||
version "18.8.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.8.2.tgz#17d42c6322d917764dd3d2d3a10d7884925de067"
|
||||
integrity sha512-cRMwIgdDN43GO4xMWAfJAecYn8wV4JbsOGHNfNUIDiuYkUYAR5ec4Rj7IO2SAhFPEfpPtLtUTbbny/TCT7aDwA==
|
||||
|
||||
"@types/normalize-package-data@^2.4.0":
|
||||
version "2.4.1"
|
||||
@ -1540,14 +1563,14 @@
|
||||
"@typescript-eslint/typescript-estree" "5.32.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/parser@^5.37.0":
|
||||
version "5.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.38.0.tgz#5a59a1ff41a7b43aacd1bb2db54f6bf1c02b2ff8"
|
||||
integrity sha512-/F63giJGLDr0ms1Cr8utDAxP2SPiglaD6V+pCOcG35P2jCqdfR7uuEhz1GIC3oy4hkUF8xA1XSXmd9hOh/a5EA==
|
||||
"@typescript-eslint/parser@^5.38.1":
|
||||
version "5.39.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.39.0.tgz#93fa0bc980a3a501e081824f6097f7ca30aaa22b"
|
||||
integrity sha512-PhxLjrZnHShe431sBAGHaNe6BDdxAASDySgsBCGxcBecVCi8NQWxQZMcizNA4g0pN51bBAn/FUfkWG3SDVcGlA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.38.0"
|
||||
"@typescript-eslint/types" "5.38.0"
|
||||
"@typescript-eslint/typescript-estree" "5.38.0"
|
||||
"@typescript-eslint/scope-manager" "5.39.0"
|
||||
"@typescript-eslint/types" "5.39.0"
|
||||
"@typescript-eslint/typescript-estree" "5.39.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.29.0":
|
||||
@ -1566,13 +1589,13 @@
|
||||
"@typescript-eslint/types" "5.32.0"
|
||||
"@typescript-eslint/visitor-keys" "5.32.0"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.38.0":
|
||||
version "5.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.38.0.tgz#8f0927024b6b24e28671352c93b393a810ab4553"
|
||||
integrity sha512-ByhHIuNyKD9giwkkLqzezZ9y5bALW8VNY6xXcP+VxoH4JBDKjU5WNnsiD4HJdglHECdV+lyaxhvQjTUbRboiTA==
|
||||
"@typescript-eslint/scope-manager@5.39.0":
|
||||
version "5.39.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.39.0.tgz#873e1465afa3d6c78d8ed2da68aed266a08008d0"
|
||||
integrity sha512-/I13vAqmG3dyqMVSZPjsbuNQlYS082Y7OMkwhCfLXYsmlI0ca4nkL7wJ/4gjX70LD4P8Hnw1JywUVVAwepURBw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.38.0"
|
||||
"@typescript-eslint/visitor-keys" "5.38.0"
|
||||
"@typescript-eslint/types" "5.39.0"
|
||||
"@typescript-eslint/visitor-keys" "5.39.0"
|
||||
|
||||
"@typescript-eslint/type-utils@5.29.0":
|
||||
version "5.29.0"
|
||||
@ -1593,10 +1616,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.32.0.tgz#484273021eeeae87ddb288f39586ef5efeb6dcd8"
|
||||
integrity sha512-EBUKs68DOcT/EjGfzywp+f8wG9Zw6gj6BjWu7KV/IYllqKJFPlZlLSYw/PTvVyiRw50t6wVbgv4p9uE2h6sZrQ==
|
||||
|
||||
"@typescript-eslint/types@5.38.0":
|
||||
version "5.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.38.0.tgz#8cd15825e4874354e31800dcac321d07548b8a5f"
|
||||
integrity sha512-HHu4yMjJ7i3Cb+8NUuRCdOGu2VMkfmKyIJsOr9PfkBVYLYrtMCK/Ap50Rpov+iKpxDTfnqvDbuPLgBE5FwUNfA==
|
||||
"@typescript-eslint/types@5.39.0":
|
||||
version "5.39.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.39.0.tgz#f4e9f207ebb4579fd854b25c0bf64433bb5ed78d"
|
||||
integrity sha512-gQMZrnfEBFXK38hYqt8Lkwt8f4U6yq+2H5VDSgP/qiTzC8Nw8JO3OuSUOQ2qW37S/dlwdkHDntkZM6SQhKyPhw==
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.29.0":
|
||||
version "5.29.0"
|
||||
@ -1624,13 +1647,13 @@
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.38.0":
|
||||
version "5.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.0.tgz#89f86b2279815c6fb7f57d68cf9b813f0dc25d98"
|
||||
integrity sha512-6P0RuphkR+UuV7Avv7MU3hFoWaGcrgOdi8eTe1NwhMp2/GjUJoODBTRWzlHpZh6lFOaPmSvgxGlROa0Sg5Zbyg==
|
||||
"@typescript-eslint/typescript-estree@5.39.0":
|
||||
version "5.39.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.39.0.tgz#c0316aa04a1a1f4f7f9498e3c13ef1d3dc4cf88b"
|
||||
integrity sha512-qLFQP0f398sdnogJoLtd43pUgB18Q50QSA+BTE5h3sUxySzbWDpTSdgt4UyxNSozY/oDK2ta6HVAzvGgq8JYnA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.38.0"
|
||||
"@typescript-eslint/visitor-keys" "5.38.0"
|
||||
"@typescript-eslint/types" "5.39.0"
|
||||
"@typescript-eslint/visitor-keys" "5.39.0"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
is-glob "^4.0.3"
|
||||
@ -1665,12 +1688,12 @@
|
||||
"@typescript-eslint/types" "5.32.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.38.0":
|
||||
version "5.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.0.tgz#60591ca3bf78aa12b25002c0993d067c00887e34"
|
||||
integrity sha512-MxnrdIyArnTi+XyFLR+kt/uNAcdOnmT+879os7qDRI+EYySR4crXJq9BXPfRzzLGq0wgxkwidrCJ9WCAoacm1w==
|
||||
"@typescript-eslint/visitor-keys@5.39.0":
|
||||
version "5.39.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.39.0.tgz#8f41f7d241b47257b081ddba5d3ce80deaae61e2"
|
||||
integrity sha512-yyE3RPwOG+XJBLrhvsxAidUgybJVQ/hG8BhiJo0k8JSAYfk/CshVcxf0HwP4Jt7WZZ6vLmxdo1p6EyN3tzFTkg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.38.0"
|
||||
"@typescript-eslint/types" "5.39.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@vue/babel-helper-vue-jsx-merge-props@^1.2.1":
|
||||
@ -1929,47 +1952,47 @@
|
||||
semver "^7.3.4"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
"@vue/compiler-core@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.39.tgz#0d77e635f4bdb918326669155a2dc977c053943e"
|
||||
integrity sha512-mf/36OWXqWn0wsC40nwRRGheR/qoID+lZXbIuLnr4/AngM0ov8Xvv8GHunC0rKRIkh60bTqydlqTeBo49rlbqw==
|
||||
"@vue/compiler-core@3.2.40":
|
||||
version "3.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.40.tgz#c785501f09536748121e937fb87605bbb1ada8e5"
|
||||
integrity sha512-2Dc3Stk0J/VyQ4OUr2yEC53kU28614lZS+bnrCbFSAIftBJ40g/2yQzf4mPBiFuqguMB7hyHaujdgZAQ67kZYA==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/shared" "3.2.39"
|
||||
"@vue/shared" "3.2.40"
|
||||
estree-walker "^2.0.2"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-dom@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.39.tgz#bd69d35c1a48fe2cea4ab9e96d2a3a735d146fdf"
|
||||
integrity sha512-HMFI25Be1C8vLEEv1hgEO1dWwG9QQ8LTTPmCkblVJY/O3OvWx6r1+zsox5mKPMGvqYEZa6l8j+xgOfUspgo7hw==
|
||||
"@vue/compiler-dom@3.2.40":
|
||||
version "3.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.40.tgz#c225418773774db536174d30d3f25ba42a33e7e4"
|
||||
integrity sha512-OZCNyYVC2LQJy4H7h0o28rtk+4v+HMQygRTpmibGoG9wZyomQiS5otU7qo3Wlq5UfHDw2RFwxb9BJgKjVpjrQw==
|
||||
dependencies:
|
||||
"@vue/compiler-core" "3.2.39"
|
||||
"@vue/shared" "3.2.39"
|
||||
"@vue/compiler-core" "3.2.40"
|
||||
"@vue/shared" "3.2.40"
|
||||
|
||||
"@vue/compiler-sfc@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.39.tgz#8fe29990f672805b7c5a2ecfa5b05e681c862ea2"
|
||||
integrity sha512-fqAQgFs1/BxTUZkd0Vakn3teKUt//J3c420BgnYgEOoVdTwYpBTSXCMJ88GOBCylmUBbtquGPli9tVs7LzsWIA==
|
||||
"@vue/compiler-sfc@3.2.40":
|
||||
version "3.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.40.tgz#61823283efc84d25d9d2989458f305d32a2ed141"
|
||||
integrity sha512-tzqwniIN1fu1PDHC3CpqY/dPCfN/RN1thpBC+g69kJcrl7mbGiHKNwbA6kJ3XKKy8R6JLKqcpVugqN4HkeBFFg==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/compiler-core" "3.2.39"
|
||||
"@vue/compiler-dom" "3.2.39"
|
||||
"@vue/compiler-ssr" "3.2.39"
|
||||
"@vue/reactivity-transform" "3.2.39"
|
||||
"@vue/shared" "3.2.39"
|
||||
"@vue/compiler-core" "3.2.40"
|
||||
"@vue/compiler-dom" "3.2.40"
|
||||
"@vue/compiler-ssr" "3.2.40"
|
||||
"@vue/reactivity-transform" "3.2.40"
|
||||
"@vue/shared" "3.2.40"
|
||||
estree-walker "^2.0.2"
|
||||
magic-string "^0.25.7"
|
||||
postcss "^8.1.10"
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@vue/compiler-ssr@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.39.tgz#4f3bfb535cb98b764bee45e078700e03ccc60633"
|
||||
integrity sha512-EoGCJ6lincKOZGW+0Ky4WOKsSmqL7hp1ZYgen8M7u/mlvvEQUaO9tKKOy7K43M9U2aA3tPv0TuYYQFrEbK2eFQ==
|
||||
"@vue/compiler-ssr@3.2.40":
|
||||
version "3.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.40.tgz#67df95a096c63e9ec4b50b84cc6f05816793629c"
|
||||
integrity sha512-80cQcgasKjrPPuKcxwuCx7feq+wC6oFl5YaKSee9pV3DNq+6fmCVwEEC3vvkf/E2aI76rIJSOYHsWSEIxK74oQ==
|
||||
dependencies:
|
||||
"@vue/compiler-dom" "3.2.39"
|
||||
"@vue/shared" "3.2.39"
|
||||
"@vue/compiler-dom" "3.2.40"
|
||||
"@vue/shared" "3.2.40"
|
||||
|
||||
"@vue/component-compiler-utils@^3.1.0", "@vue/component-compiler-utils@^3.3.0":
|
||||
version "3.3.0"
|
||||
@ -2001,53 +2024,53 @@
|
||||
"@typescript-eslint/parser" "^5.0.0"
|
||||
vue-eslint-parser "^9.0.0"
|
||||
|
||||
"@vue/reactivity-transform@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.39.tgz#da6ae6c8fd77791b9ae21976720d116591e1c4aa"
|
||||
integrity sha512-HGuWu864zStiWs9wBC6JYOP1E00UjMdDWIG5W+FpUx28hV3uz9ODOKVNm/vdOy/Pvzg8+OcANxAVC85WFBbl3A==
|
||||
"@vue/reactivity-transform@3.2.40":
|
||||
version "3.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.40.tgz#dc24b9074b26f0d9dd2034c6349f5bb2a51c86ac"
|
||||
integrity sha512-HQUCVwEaacq6fGEsg2NUuGKIhUveMCjOk8jGHqLXPI2w6zFoPrlQhwWEaINTv5kkZDXKEnCijAp+4gNEHG03yw==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.16.4"
|
||||
"@vue/compiler-core" "3.2.39"
|
||||
"@vue/shared" "3.2.39"
|
||||
"@vue/compiler-core" "3.2.40"
|
||||
"@vue/shared" "3.2.40"
|
||||
estree-walker "^2.0.2"
|
||||
magic-string "^0.25.7"
|
||||
|
||||
"@vue/reactivity@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.39.tgz#e6e3615fe2288d4232b104640ddabd0729a78c80"
|
||||
integrity sha512-vlaYX2a3qMhIZfrw3Mtfd+BuU+TZmvDrPMa+6lpfzS9k/LnGxkSuf0fhkP0rMGfiOHPtyKoU9OJJJFGm92beVQ==
|
||||
"@vue/reactivity@3.2.40":
|
||||
version "3.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.40.tgz#ae65496f5b364e4e481c426f391568ed7d133cca"
|
||||
integrity sha512-N9qgGLlZmtUBMHF9xDT4EkD9RdXde1Xbveb+niWMXuHVWQP5BzgRmE3SFyUBBcyayG4y1lhoz+lphGRRxxK4RA==
|
||||
dependencies:
|
||||
"@vue/shared" "3.2.39"
|
||||
"@vue/shared" "3.2.40"
|
||||
|
||||
"@vue/runtime-core@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.39.tgz#dc1faccab11b3e81197aba33fb30c9447c1d2c84"
|
||||
integrity sha512-xKH5XP57JW5JW+8ZG1khBbuLakINTgPuINKL01hStWLTTGFOrM49UfCFXBcFvWmSbci3gmJyLl2EAzCaZWsx8g==
|
||||
"@vue/runtime-core@3.2.40":
|
||||
version "3.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.40.tgz#e814358bf1b0ff6d4a6b4f8f62d9f341964fb275"
|
||||
integrity sha512-U1+rWf0H8xK8aBUZhnrN97yoZfHbjgw/bGUzfgKPJl69/mXDuSg8CbdBYBn6VVQdR947vWneQBFzdhasyzMUKg==
|
||||
dependencies:
|
||||
"@vue/reactivity" "3.2.39"
|
||||
"@vue/shared" "3.2.39"
|
||||
"@vue/reactivity" "3.2.40"
|
||||
"@vue/shared" "3.2.40"
|
||||
|
||||
"@vue/runtime-dom@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.39.tgz#4a8cb132bcef316e8151c5ed07fc7272eb064614"
|
||||
integrity sha512-4G9AEJP+sLhsqf5wXcyKVWQKUhI+iWfy0hWQgea+CpaTD7BR0KdQzvoQdZhwCY6B3oleSyNLkLAQwm0ya/wNoA==
|
||||
"@vue/runtime-dom@3.2.40":
|
||||
version "3.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.40.tgz#975119feac5ab703aa9bbbf37c9cc966602c8eab"
|
||||
integrity sha512-AO2HMQ+0s2+MCec8hXAhxMgWhFhOPJ/CyRXnmTJ6XIOnJFLrH5Iq3TNwvVcODGR295jy77I6dWPj+wvFoSYaww==
|
||||
dependencies:
|
||||
"@vue/runtime-core" "3.2.39"
|
||||
"@vue/shared" "3.2.39"
|
||||
"@vue/runtime-core" "3.2.40"
|
||||
"@vue/shared" "3.2.40"
|
||||
csstype "^2.6.8"
|
||||
|
||||
"@vue/server-renderer@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.39.tgz#4358292d925233b0d8b54cf0513eaece8b2351c5"
|
||||
integrity sha512-1yn9u2YBQWIgytFMjz4f/t0j43awKytTGVptfd3FtBk76t1pd8mxbek0G/DrnjJhd2V7mSTb5qgnxMYt8Z5iSQ==
|
||||
"@vue/server-renderer@3.2.40":
|
||||
version "3.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.2.40.tgz#55eaac31f7105c3907e1895129bf4efb6b0ce393"
|
||||
integrity sha512-gtUcpRwrXOJPJ4qyBpU3EyxQa4EkV8I4f8VrDePcGCPe4O/hd0BPS7v9OgjIQob6Ap8VDz9G+mGTKazE45/95w==
|
||||
dependencies:
|
||||
"@vue/compiler-ssr" "3.2.39"
|
||||
"@vue/shared" "3.2.39"
|
||||
"@vue/compiler-ssr" "3.2.40"
|
||||
"@vue/shared" "3.2.40"
|
||||
|
||||
"@vue/shared@3.2.39":
|
||||
version "3.2.39"
|
||||
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.39.tgz#302df167559a1a5156da162d8cc6760cef67f8e3"
|
||||
integrity sha512-D3dl2ZB9qE6mTuWPk9RlhDeP1dgNRUKC3NJxji74A4yL8M2MwlhLKUC/49WHjrNzSPug58fWx/yFbaTzGAQSBw==
|
||||
"@vue/shared@3.2.40":
|
||||
version "3.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.40.tgz#e57799da2a930b975321981fcee3d1e90ed257ae"
|
||||
integrity sha512-0PLQ6RUtZM0vO3teRfzGi4ltLUO5aO+kLgwh4Um3THSR03rpQWLTuRCkuO5A41ITzwdWeKdPHtSARuPkoo5pCQ==
|
||||
|
||||
"@vue/vue-loader-v15@npm:vue-loader@^15.9.7":
|
||||
version "15.9.8"
|
||||
@ -2487,10 +2510,10 @@ bootstrap-icons-vue@^1.8.1:
|
||||
resolved "https://registry.yarnpkg.com/bootstrap-icons-vue/-/bootstrap-icons-vue-1.8.1.tgz#ce4a0c1f6efe41dabcc1341f2cb191d307fbaf50"
|
||||
integrity sha512-uItRULwQz0epETi9x/RBEqfjHmTAmkIIczpH1R6L9T6yyaaijk0826PzTWnWNm15tw66JT/8GNuXjB0HI5PHLw==
|
||||
|
||||
bootstrap@^5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.2.1.tgz#45f97ff05cbe828bad807b014d8425f3aeb8ec3a"
|
||||
integrity sha512-UQi3v2NpVPEi1n35dmRRzBJFlgvWHYwyem6yHhuT6afYF+sziEt46McRbT//kVXZ7b1YUYEVGdXEH74Nx3xzGA==
|
||||
bootstrap@^5.2.2:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.2.2.tgz#834e053eed584a65e244d8aa112a6959f56e27a0"
|
||||
integrity sha512-dEtzMTV71n6Fhmbg4fYJzQsw1N29hJKO1js5ackCgIpDcGid2ETMGC6zwSYw09v05Y+oRdQ9loC54zB1La3hHQ==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
@ -2880,10 +2903,10 @@ core-js-compat@^3.21.0, core-js-compat@^3.22.1, core-js-compat@^3.8.3:
|
||||
browserslist "^4.20.3"
|
||||
semver "7.0.0"
|
||||
|
||||
core-js@^3.25.3:
|
||||
version "3.25.3"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.3.tgz#cbc2be50b5ddfa7981837bd8c41639f27b166593"
|
||||
integrity sha512-y1hvKXmPHvm5B7w4ln1S4uc9eV/O5+iFExSRUimnvIph11uaizFR8LFMdONN8hG3P2pipUfX4Y/fR8rAEtcHcQ==
|
||||
core-js@^3.25.5:
|
||||
version "3.25.5"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.25.5.tgz#e86f651a2ca8a0237a5f064c2fe56cef89646e27"
|
||||
integrity sha512-nbm6eZSjm+ZuBQxCUPQKQCoUEfFOXjUZ8dTTyikyKaWrTYmAVbykQfwsKE5dBK88u3QCkCrzsx/PPlKfhsvgpw==
|
||||
|
||||
core-js@^3.8.3:
|
||||
version "3.24.1"
|
||||
@ -3330,10 +3353,10 @@ escape-string-regexp@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||
|
||||
eslint-plugin-vue@^9.5.1:
|
||||
version "9.5.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.5.1.tgz#87ce075882cf7d824b95f46c224f91495fafcc54"
|
||||
integrity sha512-Y0sL2RY7Xc9S8kNih9lbwHIDmewUg9bfas6WSzsOWRgDXhIHKxRBZYNAnVcXBFfE+bMWHUA5GLChl7TcTYUI8w==
|
||||
eslint-plugin-vue@^9.6.0:
|
||||
version "9.6.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-9.6.0.tgz#5d1825b93d54595b1ba97106843e1d28cf3bb291"
|
||||
integrity sha512-zzySkJgVbFCylnG2+9MDF7N+2Rjze2y0bF8GyUNpFOnT8mCMfqqtLDJkHBuYu9N/psW1A6DVbQhPkP92E+qakA==
|
||||
dependencies:
|
||||
eslint-utils "^3.0.0"
|
||||
natural-compare "^1.4.0"
|
||||
@ -6201,10 +6224,10 @@ type-is@~1.6.18:
|
||||
media-typer "0.3.0"
|
||||
mime-types "~2.1.24"
|
||||
|
||||
typescript@^4.8.3:
|
||||
version "4.8.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.3.tgz#d59344522c4bc464a65a730ac695007fdb66dd88"
|
||||
integrity sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==
|
||||
typescript@^4.8.4:
|
||||
version "4.8.4"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6"
|
||||
integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==
|
||||
|
||||
unicode-canonical-property-names-ecmascript@^2.0.0:
|
||||
version "2.0.0"
|
||||
@ -6346,16 +6369,16 @@ vue-template-es2015-compiler@^1.9.0:
|
||||
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
|
||||
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
|
||||
|
||||
vue@^3.2.39:
|
||||
version "3.2.39"
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.39.tgz#de071c56c4c32c41cbd54e55f11404295c0dd62d"
|
||||
integrity sha512-tRkguhRTw9NmIPXhzk21YFBqXHT2t+6C6wPOgQ50fcFVWnPdetmRqbmySRHznrYjX2E47u0cGlKGcxKZJ38R/g==
|
||||
vue@^3.2.40:
|
||||
version "3.2.40"
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.40.tgz#23f387f6f9b3a0767938db6751e4fb5900f0ee34"
|
||||
integrity sha512-1mGHulzUbl2Nk3pfvI5aXYYyJUs1nm4kyvuz38u4xlQkLUn1i2R7nDbI4TufECmY8v1qNBHYy62bCaM+3cHP2A==
|
||||
dependencies:
|
||||
"@vue/compiler-dom" "3.2.39"
|
||||
"@vue/compiler-sfc" "3.2.39"
|
||||
"@vue/runtime-dom" "3.2.39"
|
||||
"@vue/server-renderer" "3.2.39"
|
||||
"@vue/shared" "3.2.39"
|
||||
"@vue/compiler-dom" "3.2.40"
|
||||
"@vue/compiler-sfc" "3.2.40"
|
||||
"@vue/runtime-dom" "3.2.40"
|
||||
"@vue/server-renderer" "3.2.40"
|
||||
"@vue/shared" "3.2.40"
|
||||
|
||||
watchpack@^2.3.1:
|
||||
version "2.3.1"
|
||||
|
||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user