Merge branch 'development'
This commit is contained in:
commit
4d0f958943
@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <cstdint>
|
||||
|
||||
#define CONFIG_FILENAME "/config.json"
|
||||
#define CONFIG_VERSION 0x00011900 // 0.1.24 // make sure to clean all after change
|
||||
@ -54,6 +54,9 @@ struct INVERTER_CONFIG_T {
|
||||
bool Poll_Enable_Night;
|
||||
bool Command_Enable;
|
||||
bool Command_Enable_Night;
|
||||
uint8_t ReachableThreshold;
|
||||
bool ZeroRuntimeDataIfUnrechable;
|
||||
bool ZeroYieldDayOnMidnight;
|
||||
CHANNEL_CONFIG_T channel[INV_MAX_CHAN_COUNT];
|
||||
};
|
||||
|
||||
@ -72,18 +75,18 @@ struct POWERMETER_HTTP_PHASE_CONFIG_T {
|
||||
|
||||
struct CONFIG_T {
|
||||
uint32_t Cfg_Version;
|
||||
uint Cfg_SaveCount;
|
||||
uint32_t Cfg_SaveCount;
|
||||
|
||||
char WiFi_Ssid[WIFI_MAX_SSID_STRLEN + 1];
|
||||
char WiFi_Password[WIFI_MAX_PASSWORD_STRLEN + 1];
|
||||
byte WiFi_Ip[4];
|
||||
byte WiFi_Netmask[4];
|
||||
byte WiFi_Gateway[4];
|
||||
byte WiFi_Dns1[4];
|
||||
byte WiFi_Dns2[4];
|
||||
uint8_t WiFi_Ip[4];
|
||||
uint8_t WiFi_Netmask[4];
|
||||
uint8_t WiFi_Gateway[4];
|
||||
uint8_t WiFi_Dns1[4];
|
||||
uint8_t WiFi_Dns2[4];
|
||||
bool WiFi_Dhcp;
|
||||
char WiFi_Hostname[WIFI_MAX_HOSTNAME_STRLEN + 1];
|
||||
uint WiFi_ApTimeout;
|
||||
uint32_t WiFi_ApTimeout;
|
||||
|
||||
char Ntp_Server[NTP_MAX_SERVER_STRLEN + 1];
|
||||
char Ntp_Timezone[NTP_MAX_TIMEZONE_STRLEN + 1];
|
||||
@ -95,7 +98,7 @@ struct CONFIG_T {
|
||||
bool Mqtt_Enabled;
|
||||
char Mqtt_Hostname[MQTT_MAX_HOSTNAME_STRLEN + 1];
|
||||
bool Mqtt_VerboseLogging;
|
||||
uint Mqtt_Port;
|
||||
uint32_t Mqtt_Port;
|
||||
char Mqtt_Username[MQTT_MAX_USERNAME_STRLEN + 1];
|
||||
char Mqtt_Password[MQTT_MAX_PASSWORD_STRLEN + 1];
|
||||
char Mqtt_Topic[MQTT_MAX_TOPIC_STRLEN + 1];
|
||||
@ -104,6 +107,7 @@ struct CONFIG_T {
|
||||
char Mqtt_LwtValue_Online[MQTT_MAX_LWTVALUE_STRLEN + 1];
|
||||
char Mqtt_LwtValue_Offline[MQTT_MAX_LWTVALUE_STRLEN + 1];
|
||||
uint32_t Mqtt_PublishInterval;
|
||||
bool Mqtt_CleanSession;
|
||||
|
||||
INVERTER_CONFIG_T Inverter[INV_MAX_COUNT];
|
||||
|
||||
|
||||
@ -31,16 +31,16 @@ public:
|
||||
float getTotalDcIrradiation();
|
||||
|
||||
// Amount of relevant digits for yield total
|
||||
unsigned int getTotalAcYieldTotalDigits();
|
||||
uint32_t getTotalAcYieldTotalDigits();
|
||||
|
||||
// Amount of relevant digits for yield total
|
||||
unsigned int getTotalAcYieldDayDigits();
|
||||
uint32_t getTotalAcYieldDayDigits();
|
||||
|
||||
// Amount of relevant digits for AC power
|
||||
unsigned int getTotalAcPowerDigits();
|
||||
uint32_t getTotalAcPowerDigits();
|
||||
|
||||
// Amount of relevant digits for DC power
|
||||
unsigned int getTotalDcPowerDigits();
|
||||
uint32_t getTotalDcPowerDigits();
|
||||
|
||||
// True, if at least one inverter is reachable
|
||||
bool getIsAtLeastOneReachable();
|
||||
@ -68,10 +68,10 @@ private:
|
||||
float _totalDcPowerIrradiation = 0;
|
||||
float _totalDcIrradiationInstalled = 0;
|
||||
float _totalDcIrradiation = 0;
|
||||
unsigned int _totalAcYieldTotalDigits = 0;
|
||||
unsigned int _totalAcYieldDayDigits = 0;
|
||||
unsigned int _totalAcPowerDigits = 0;
|
||||
unsigned int _totalDcPowerDigits = 0;
|
||||
uint32_t _totalAcYieldTotalDigits = 0;
|
||||
uint32_t _totalAcYieldDayDigits = 0;
|
||||
uint32_t _totalAcPowerDigits = 0;
|
||||
uint32_t _totalDcPowerDigits = 0;
|
||||
bool _isAtLeastOneReachable = false;
|
||||
bool _isAtLeastOneProducing = false;
|
||||
bool _isAllEnabledProducing = false;
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include "Configuration.h"
|
||||
#include <Hoymiles.h>
|
||||
#include <TimeoutHelper.h>
|
||||
#include <espMqttClient.h>
|
||||
|
||||
class MqttHandleInverterClass {
|
||||
|
||||
@ -63,10 +63,10 @@ private:
|
||||
void NetworkEvent(WiFiEvent_t event);
|
||||
bool adminEnabled = true;
|
||||
bool forceDisconnection = false;
|
||||
int adminTimeoutCounter = 0;
|
||||
int adminTimeoutCounterMax = 0;
|
||||
int connectTimeoutTimer = 0;
|
||||
int connectRedoTimer = 0;
|
||||
uint32_t adminTimeoutCounter = 0;
|
||||
uint32_t adminTimeoutCounterMax = 0;
|
||||
uint32_t connectTimeoutTimer = 0;
|
||||
uint32_t connectRedoTimer = 0;
|
||||
uint32_t lastTimerCall = 0;
|
||||
const byte DNS_PORT = 53;
|
||||
IPAddress apIp;
|
||||
|
||||
@ -22,8 +22,8 @@ private:
|
||||
SunSet _sun;
|
||||
bool _isDayPeriod = true;
|
||||
bool _isSunsetAvailable = true;
|
||||
uint _sunriseMinutes = 0;
|
||||
uint _sunsetMinutes = 0;
|
||||
uint32_t _sunriseMinutes = 0;
|
||||
uint32_t _sunsetMinutes = 0;
|
||||
|
||||
uint32_t _lastUpdate = 0;
|
||||
bool _isValidInfo = false;
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "WebApi_dtu.h"
|
||||
#include "WebApi_eventlog.h"
|
||||
#include "WebApi_firmware.h"
|
||||
#include "WebApi_gridprofile.h"
|
||||
#include "WebApi_inverter.h"
|
||||
#include "WebApi_limit.h"
|
||||
#include "WebApi_maintenance.h"
|
||||
@ -52,6 +53,7 @@ private:
|
||||
WebApiDtuClass _webApiDtu;
|
||||
WebApiEventlogClass _webApiEventlog;
|
||||
WebApiFirmwareClass _webApiFirmware;
|
||||
WebApiGridProfileClass _webApiGridprofile;
|
||||
WebApiInverterClass _webApiInverter;
|
||||
WebApiLimitClass _webApiLimit;
|
||||
WebApiMaintenanceClass _webApiMaintenance;
|
||||
|
||||
15
include/WebApi_gridprofile.h
Normal file
15
include/WebApi_gridprofile.h
Normal file
@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
class WebApiGridProfileClass {
|
||||
public:
|
||||
void init(AsyncWebServer* server);
|
||||
void loop();
|
||||
|
||||
private:
|
||||
void onGridProfileStatus(AsyncWebServerRequest* request);
|
||||
|
||||
AsyncWebServer* _server;
|
||||
};
|
||||
@ -25,4 +25,6 @@ private:
|
||||
uint32_t _lastInvUpdateCheck = 0;
|
||||
uint32_t _lastWsCleanup = 0;
|
||||
uint32_t _newestInverterTimestamp = 0;
|
||||
|
||||
std::mutex _mutex;
|
||||
};
|
||||
@ -74,6 +74,7 @@
|
||||
#define MQTT_LWT_ONLINE "online"
|
||||
#define MQTT_LWT_OFFLINE "offline"
|
||||
#define MQTT_PUBLISH_INTERVAL 5U
|
||||
#define MQTT_CLEAN_SESSION true
|
||||
|
||||
#define DTU_SERIAL 0x99978563412U
|
||||
#define DTU_POLL_INTERVAL 5U
|
||||
@ -95,6 +96,8 @@
|
||||
#define DISPLAY_CONTRAST 60U
|
||||
#define DISPLAY_LANGUAGE 0U
|
||||
|
||||
#define REACHABLE_THRESHOLD 2U
|
||||
|
||||
#define VEDIRECT_ENABLED false
|
||||
#define VEDIRECT_VERBOSE_LOGGING false
|
||||
#define VEDIRECT_UPDATESONLY true
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
* Copyright (C) 2022 Thomas Basler and others
|
||||
*/
|
||||
#include "Hoymiles.h"
|
||||
#include "Utils.h"
|
||||
#include "inverters/HMS_1CH.h"
|
||||
#include "inverters/HMS_2CH.h"
|
||||
#include "inverters/HMS_4CH.h"
|
||||
@ -12,18 +13,10 @@
|
||||
#include "inverters/HM_4CH.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
#define HOY_SEMAPHORE_TAKE() \
|
||||
do { \
|
||||
} while (xSemaphoreTake(_xSemaphore, portMAX_DELAY) != pdPASS)
|
||||
#define HOY_SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore)
|
||||
|
||||
HoymilesClass Hoymiles;
|
||||
|
||||
void HoymilesClass::init()
|
||||
{
|
||||
_xSemaphore = xSemaphoreCreateMutex();
|
||||
HOY_SEMAPHORE_GIVE(); // release before first use
|
||||
|
||||
_pollInterval = 0;
|
||||
_radioNrf.reset(new HoymilesRadio_NRF());
|
||||
_radioCmt.reset(new HoymilesRadio_CMT());
|
||||
@ -41,7 +34,7 @@ void HoymilesClass::initCMT(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8
|
||||
|
||||
void HoymilesClass::loop()
|
||||
{
|
||||
HOY_SEMAPHORE_TAKE();
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
_radioNrf->loop();
|
||||
_radioCmt->loop();
|
||||
|
||||
@ -57,6 +50,8 @@ void HoymilesClass::loop()
|
||||
}
|
||||
|
||||
if (iv != nullptr && iv->getRadio()->isInitialized() && iv->getRadio()->isQueueEmpty()) {
|
||||
|
||||
if (iv->getEnablePolling() || iv->getEnableCommands()) {
|
||||
_messageOutput->print("Fetch inverter: ");
|
||||
_messageOutput->println(iv->serial(), HEX);
|
||||
|
||||
@ -71,8 +66,7 @@ void HoymilesClass::loop()
|
||||
iv->sendAlarmLogRequest(force);
|
||||
|
||||
// Fetch limit
|
||||
if ((iv->SystemConfigPara()->getLastLimitRequestSuccess() == CMD_NOK)
|
||||
|| ((millis() - iv->SystemConfigPara()->getLastUpdateRequest() > HOY_SYSTEM_CONFIG_PARA_POLL_INTERVAL)
|
||||
if (((millis() - iv->SystemConfigPara()->getLastUpdateRequest() > HOY_SYSTEM_CONFIG_PARA_POLL_INTERVAL)
|
||||
&& (millis() - iv->SystemConfigPara()->getLastUpdateCommand() > HOY_SYSTEM_CONFIG_PARA_POLL_MIN_DURATION))) {
|
||||
_messageOutput->println("Request SystemConfigPara");
|
||||
iv->sendSystemConfigParaRequest();
|
||||
@ -108,16 +102,38 @@ void HoymilesClass::loop()
|
||||
}
|
||||
}
|
||||
|
||||
if (++inverterPos >= getNumInverters()) {
|
||||
inverterPos = 0;
|
||||
// Fetch grid profile
|
||||
if (iv->Statistics()->getLastUpdate() > 0 && iv->GridProfile()->getLastUpdate() == 0) {
|
||||
iv->sendGridOnProFileParaRequest();
|
||||
}
|
||||
|
||||
_lastPoll = millis();
|
||||
}
|
||||
|
||||
if (++inverterPos >= getNumInverters()) {
|
||||
inverterPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
HOY_SEMAPHORE_GIVE();
|
||||
// Perform housekeeping of all inverters on day change
|
||||
int8_t currentWeekDay = Utils::getWeekDay();
|
||||
static int8_t lastWeekDay = -1;
|
||||
if (lastWeekDay == -1) {
|
||||
lastWeekDay = currentWeekDay;
|
||||
} else {
|
||||
if (currentWeekDay != lastWeekDay) {
|
||||
|
||||
for (auto& inv : _inverters) {
|
||||
if (inv->getZeroYieldDayOnMidnight()) {
|
||||
inv->Statistics()->zeroDailyData();
|
||||
}
|
||||
}
|
||||
|
||||
lastWeekDay = currentWeekDay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<InverterAbstract> HoymilesClass::addInverter(const char* name, uint64_t serial)
|
||||
@ -195,9 +211,8 @@ void HoymilesClass::removeInverterBySerial(uint64_t serial)
|
||||
{
|
||||
for (uint8_t i = 0; i < _inverters.size(); i++) {
|
||||
if (_inverters[i]->serial() == serial) {
|
||||
HOY_SEMAPHORE_TAKE();
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
_inverters.erase(_inverters.begin() + i);
|
||||
HOY_SEMAPHORE_GIVE();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ private:
|
||||
std::unique_ptr<HoymilesRadio_NRF> _radioNrf;
|
||||
std::unique_ptr<HoymilesRadio_CMT> _radioCmt;
|
||||
|
||||
SemaphoreHandle_t _xSemaphore;
|
||||
std::mutex _mutex;
|
||||
|
||||
uint32_t _pollInterval = 0;
|
||||
bool _verboseLogging = true;
|
||||
|
||||
15
lib/Hoymiles/src/Utils.cpp
Normal file
15
lib/Hoymiles/src/Utils.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2023 Thomas Basler and others
|
||||
*/
|
||||
#include "Utils.h"
|
||||
#include <time.h>
|
||||
|
||||
uint8_t Utils::getWeekDay()
|
||||
{
|
||||
time_t raw;
|
||||
struct tm info;
|
||||
time(&raw);
|
||||
localtime_r(&raw, &info);
|
||||
return info.tm_mday;
|
||||
}
|
||||
9
lib/Hoymiles/src/Utils.h
Normal file
9
lib/Hoymiles/src/Utils.h
Normal file
@ -0,0 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class Utils {
|
||||
public:
|
||||
static uint8_t getWeekDay();
|
||||
};
|
||||
40
lib/Hoymiles/src/commands/GridOnProFilePara.cpp
Normal file
40
lib/Hoymiles/src/commands/GridOnProFilePara.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2022 Thomas Basler and others
|
||||
*/
|
||||
#include "GridOnProFilePara.h"
|
||||
#include "Hoymiles.h"
|
||||
#include "inverters/InverterAbstract.h"
|
||||
|
||||
GridOnProFilePara::GridOnProFilePara(uint64_t target_address, uint64_t router_address, time_t time)
|
||||
: MultiDataCommand(target_address, router_address)
|
||||
{
|
||||
setTime(time);
|
||||
setDataType(0x02);
|
||||
setTimeout(500);
|
||||
}
|
||||
|
||||
String GridOnProFilePara::getCommandName()
|
||||
{
|
||||
return "GridOnProFilePara";
|
||||
}
|
||||
|
||||
bool GridOnProFilePara::handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id)
|
||||
{
|
||||
// Check CRC of whole payload
|
||||
if (!MultiDataCommand::handleResponse(inverter, fragment, max_fragment_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Move all fragments into target buffer
|
||||
uint8_t offs = 0;
|
||||
inverter->GridProfile()->beginAppendFragment();
|
||||
inverter->GridProfile()->clearBuffer();
|
||||
for (uint8_t i = 0; i < max_fragment_id; i++) {
|
||||
inverter->GridProfile()->appendFragment(offs, fragment[i].fragment, fragment[i].len);
|
||||
offs += (fragment[i].len);
|
||||
}
|
||||
inverter->GridProfile()->endAppendFragment();
|
||||
inverter->GridProfile()->setLastUpdate(millis());
|
||||
return true;
|
||||
}
|
||||
13
lib/Hoymiles/src/commands/GridOnProFilePara.h
Normal file
13
lib/Hoymiles/src/commands/GridOnProFilePara.h
Normal file
@ -0,0 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#include "MultiDataCommand.h"
|
||||
|
||||
class GridOnProFilePara : public MultiDataCommand {
|
||||
public:
|
||||
explicit GridOnProFilePara(uint64_t target_address = 0, uint64_t router_address = 0, time_t time = 0);
|
||||
|
||||
virtual String getCommandName();
|
||||
|
||||
virtual bool handleResponse(InverterAbstract* inverter, fragment_t fragment[], uint8_t max_fragment_id);
|
||||
};
|
||||
@ -8,6 +8,7 @@
|
||||
* AlarmDataCommand
|
||||
* DevInfoAllCommand
|
||||
* DevInfoSimpleCommand
|
||||
* GridOnProFilePara
|
||||
* RealTimeRunDataCommand
|
||||
* SystemConfigParaCommand
|
||||
* ParaSetCommand
|
||||
|
||||
@ -55,4 +55,9 @@ bool RealTimeRunDataCommand::handleResponse(InverterAbstract* inverter, fragment
|
||||
void RealTimeRunDataCommand::gotTimeout(InverterAbstract* inverter)
|
||||
{
|
||||
inverter->Statistics()->incrementRxFailureCount();
|
||||
|
||||
if (inverter->getZeroValuesIfUnreachable() && !inverter->isReachable()) {
|
||||
Hoymiles.getMessageOutput()->println("Set runtime data to zero");
|
||||
inverter->Statistics()->zeroRuntimeData();
|
||||
}
|
||||
}
|
||||
@ -3,6 +3,7 @@
|
||||
* Copyright (C) 2022 Thomas Basler and others
|
||||
*/
|
||||
#include "SystemConfigParaCommand.h"
|
||||
#include "Hoymiles.h"
|
||||
#include "inverters/InverterAbstract.h"
|
||||
|
||||
SystemConfigParaCommand::SystemConfigParaCommand(uint64_t target_address, uint64_t router_address, time_t time)
|
||||
@ -25,6 +26,18 @@ bool SystemConfigParaCommand::handleResponse(InverterAbstract* inverter, fragmen
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if at least all required bytes are received
|
||||
// In case of low power in the inverter it occours that some incomplete fragments
|
||||
// with a valid CRC are received.
|
||||
uint8_t fragmentsSize = getTotalFragmentSize(fragment, max_fragment_id);
|
||||
uint8_t expectedSize = inverter->SystemConfigPara()->getExpectedByteCount();
|
||||
if (fragmentsSize < expectedSize) {
|
||||
Hoymiles.getMessageOutput()->printf("ERROR in %s: Received fragment size: %d, min expected size: %d\r\n",
|
||||
getCommandName().c_str(), fragmentsSize, expectedSize);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Move all fragments into target buffer
|
||||
uint8_t offs = 0;
|
||||
inverter->SystemConfigPara()->beginAppendFragment();
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "commands/AlarmDataCommand.h"
|
||||
#include "commands/DevInfoAllCommand.h"
|
||||
#include "commands/DevInfoSimpleCommand.h"
|
||||
#include "commands/GridOnProFilePara.h"
|
||||
#include "commands/PowerControlCommand.h"
|
||||
#include "commands/RealTimeRunDataCommand.h"
|
||||
#include "commands/SystemConfigParaCommand.h"
|
||||
@ -211,3 +212,25 @@ bool HM_Abstract::resendPowerControlRequest()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool HM_Abstract::sendGridOnProFileParaRequest()
|
||||
{
|
||||
if (!getEnablePolling()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct tm timeinfo;
|
||||
if (!getLocalTime(&timeinfo, 5)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
time_t now;
|
||||
time(&now);
|
||||
|
||||
auto cmd = _radio->prepareCommand<GridOnProFilePara>();
|
||||
cmd->setTime(now);
|
||||
cmd->setTargetAddress(serial());
|
||||
_radio->enqueCommand(cmd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ public:
|
||||
bool sendPowerControlRequest(bool turnOn);
|
||||
bool sendRestartControlRequest();
|
||||
bool resendPowerControlRequest();
|
||||
bool sendGridOnProFileParaRequest();
|
||||
|
||||
private:
|
||||
uint8_t _lastAlarmLogCnt = 0;
|
||||
|
||||
@ -20,6 +20,7 @@ InverterAbstract::InverterAbstract(HoymilesRadio* radio, uint64_t serial)
|
||||
|
||||
_alarmLogParser.reset(new AlarmLogParser());
|
||||
_devInfoParser.reset(new DevInfoParser());
|
||||
_gridProfileParser.reset(new GridProfileParser());
|
||||
_powerCommandParser.reset(new PowerCommandParser());
|
||||
_statisticsParser.reset(new StatisticsParser());
|
||||
_systemConfigParaParser.reset(new SystemConfigParaParser());
|
||||
@ -73,7 +74,7 @@ bool InverterAbstract::isProducing()
|
||||
|
||||
bool InverterAbstract::isReachable()
|
||||
{
|
||||
return _enablePolling && Statistics()->getRxFailureCount() <= MAX_ONLINE_FAILURE_COUNT;
|
||||
return _enablePolling && Statistics()->getRxFailureCount() <= _reachableThreshold;
|
||||
}
|
||||
|
||||
void InverterAbstract::setEnablePolling(bool enabled)
|
||||
@ -96,6 +97,36 @@ bool InverterAbstract::getEnableCommands()
|
||||
return _enableCommands;
|
||||
}
|
||||
|
||||
void InverterAbstract::setReachableThreshold(uint8_t threshold)
|
||||
{
|
||||
_reachableThreshold = threshold;
|
||||
}
|
||||
|
||||
uint8_t InverterAbstract::getReachableThreshold()
|
||||
{
|
||||
return _reachableThreshold;
|
||||
}
|
||||
|
||||
void InverterAbstract::setZeroValuesIfUnreachable(bool enabled)
|
||||
{
|
||||
_zeroValuesIfUnreachable = enabled;
|
||||
}
|
||||
|
||||
bool InverterAbstract::getZeroValuesIfUnreachable()
|
||||
{
|
||||
return _zeroValuesIfUnreachable;
|
||||
}
|
||||
|
||||
void InverterAbstract::setZeroYieldDayOnMidnight(bool enabled)
|
||||
{
|
||||
_zeroYieldDayOnMidnight = enabled;
|
||||
}
|
||||
|
||||
bool InverterAbstract::getZeroYieldDayOnMidnight()
|
||||
{
|
||||
return _zeroYieldDayOnMidnight;
|
||||
}
|
||||
|
||||
bool InverterAbstract::sendChangeChannelRequest()
|
||||
{
|
||||
return false;
|
||||
@ -116,6 +147,11 @@ DevInfoParser* InverterAbstract::DevInfo()
|
||||
return _devInfoParser.get();
|
||||
}
|
||||
|
||||
GridProfileParser* InverterAbstract::GridProfile()
|
||||
{
|
||||
return _gridProfileParser.get();
|
||||
}
|
||||
|
||||
PowerCommandParser* InverterAbstract::PowerCommand()
|
||||
{
|
||||
return _powerCommandParser.get();
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include "../commands/ActivePowerControlCommand.h"
|
||||
#include "../parser/AlarmLogParser.h"
|
||||
#include "../parser/DevInfoParser.h"
|
||||
#include "../parser/GridProfileParser.h"
|
||||
#include "../parser/PowerCommandParser.h"
|
||||
#include "../parser/StatisticsParser.h"
|
||||
#include "../parser/SystemConfigParaParser.h"
|
||||
@ -24,7 +25,6 @@ enum {
|
||||
};
|
||||
|
||||
#define MAX_RF_FRAGMENT_COUNT 13
|
||||
#define MAX_ONLINE_FAILURE_COUNT 2
|
||||
|
||||
class CommandAbstract;
|
||||
|
||||
@ -49,6 +49,15 @@ public:
|
||||
void setEnableCommands(bool enabled);
|
||||
bool getEnableCommands();
|
||||
|
||||
void setReachableThreshold(uint8_t threshold);
|
||||
uint8_t getReachableThreshold();
|
||||
|
||||
void setZeroValuesIfUnreachable(bool enabled);
|
||||
bool getZeroValuesIfUnreachable();
|
||||
|
||||
void setZeroYieldDayOnMidnight(bool enabled);
|
||||
bool getZeroYieldDayOnMidnight();
|
||||
|
||||
void clearRxFragmentBuffer();
|
||||
void addRxFragment(uint8_t fragment[], uint8_t len);
|
||||
uint8_t verifyAllFragments(CommandAbstract* cmd);
|
||||
@ -63,11 +72,13 @@ public:
|
||||
virtual bool sendRestartControlRequest() = 0;
|
||||
virtual bool resendPowerControlRequest() = 0;
|
||||
virtual bool sendChangeChannelRequest();
|
||||
virtual bool sendGridOnProFileParaRequest() = 0;
|
||||
|
||||
HoymilesRadio* getRadio();
|
||||
|
||||
AlarmLogParser* EventLog();
|
||||
DevInfoParser* DevInfo();
|
||||
GridProfileParser* GridProfile();
|
||||
PowerCommandParser* PowerCommand();
|
||||
StatisticsParser* Statistics();
|
||||
SystemConfigParaParser* SystemConfigPara();
|
||||
@ -87,8 +98,14 @@ private:
|
||||
bool _enablePolling = true;
|
||||
bool _enableCommands = true;
|
||||
|
||||
uint8_t _reachableThreshold = 3;
|
||||
|
||||
bool _zeroValuesIfUnreachable = false;
|
||||
bool _zeroYieldDayOnMidnight = false;
|
||||
|
||||
std::unique_ptr<AlarmLogParser> _alarmLogParser;
|
||||
std::unique_ptr<DevInfoParser> _devInfoParser;
|
||||
std::unique_ptr<GridProfileParser> _gridProfileParser;
|
||||
std::unique_ptr<PowerCommandParser> _powerCommandParser;
|
||||
std::unique_ptr<StatisticsParser> _statisticsParser;
|
||||
std::unique_ptr<SystemConfigParaParser> _systemConfigParaParser;
|
||||
|
||||
@ -86,16 +86,9 @@ const std::array<const AlarmMessage_t, ALARM_MSG_COUNT> AlarmLogParser::_alarmMe
|
||||
{ AlarmMessageType_t::ALL, 9000, "Microinverter is suspected of being stolen" },
|
||||
} };
|
||||
|
||||
#define HOY_SEMAPHORE_TAKE() \
|
||||
do { \
|
||||
} while (xSemaphoreTake(_xSemaphore, portMAX_DELAY) != pdPASS)
|
||||
#define HOY_SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore)
|
||||
|
||||
AlarmLogParser::AlarmLogParser()
|
||||
: Parser()
|
||||
{
|
||||
_xSemaphore = xSemaphoreCreateMutex();
|
||||
HOY_SEMAPHORE_GIVE(); // release before first use
|
||||
clearBuffer();
|
||||
}
|
||||
|
||||
@ -115,16 +108,6 @@ void AlarmLogParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t le
|
||||
_alarmLogLength += len;
|
||||
}
|
||||
|
||||
void AlarmLogParser::beginAppendFragment()
|
||||
{
|
||||
HOY_SEMAPHORE_TAKE();
|
||||
}
|
||||
|
||||
void AlarmLogParser::endAppendFragment()
|
||||
{
|
||||
HOY_SEMAPHORE_GIVE();
|
||||
}
|
||||
|
||||
uint8_t AlarmLogParser::getEntryCount()
|
||||
{
|
||||
if (_alarmLogLength < 2) {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
#include "Parser.h"
|
||||
#include <Arduino.h>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
@ -34,8 +33,6 @@ public:
|
||||
AlarmLogParser();
|
||||
void clearBuffer();
|
||||
void appendFragment(uint8_t offset, uint8_t* payload, uint8_t len);
|
||||
void beginAppendFragment();
|
||||
void endAppendFragment();
|
||||
|
||||
uint8_t getEntryCount();
|
||||
void getLogEntry(uint8_t entryId, AlarmLogEntry_t* entry);
|
||||
@ -56,6 +53,4 @@ private:
|
||||
AlarmMessageType_t _messageType = AlarmMessageType_t::ALL;
|
||||
|
||||
static const std::array<const AlarmMessage_t, ALARM_MSG_COUNT> _alarmMessages;
|
||||
|
||||
SemaphoreHandle_t _xSemaphore;
|
||||
};
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2022 Thomas Basler and others
|
||||
* Copyright (C) 2022 - 2023 Thomas Basler and others
|
||||
*/
|
||||
#include "DevInfoParser.h"
|
||||
#include "../Hoymiles.h"
|
||||
@ -46,16 +46,9 @@ const devInfo_t devInfo[] = {
|
||||
{ { 0x10, 0x33, 0x31, ALL }, 2250, "HMT-2250" } // 01
|
||||
};
|
||||
|
||||
#define HOY_SEMAPHORE_TAKE() \
|
||||
do { \
|
||||
} while (xSemaphoreTake(_xSemaphore, portMAX_DELAY) != pdPASS)
|
||||
#define HOY_SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore)
|
||||
|
||||
DevInfoParser::DevInfoParser()
|
||||
: Parser()
|
||||
{
|
||||
_xSemaphore = xSemaphoreCreateMutex();
|
||||
HOY_SEMAPHORE_GIVE(); // release before first use
|
||||
clearBufferSimple();
|
||||
clearBufferAll();
|
||||
}
|
||||
@ -92,16 +85,6 @@ void DevInfoParser::appendFragmentSimple(uint8_t offset, uint8_t* payload, uint8
|
||||
_devInfoSimpleLength += len;
|
||||
}
|
||||
|
||||
void DevInfoParser::beginAppendFragment()
|
||||
{
|
||||
HOY_SEMAPHORE_TAKE();
|
||||
}
|
||||
|
||||
void DevInfoParser::endAppendFragment()
|
||||
{
|
||||
HOY_SEMAPHORE_GIVE();
|
||||
}
|
||||
|
||||
uint32_t DevInfoParser::getLastUpdateAll()
|
||||
{
|
||||
return _lastUpdateAll;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
#include "Parser.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
#define DEV_INFO_SIZE 20
|
||||
|
||||
@ -14,9 +13,6 @@ public:
|
||||
void clearBufferSimple();
|
||||
void appendFragmentSimple(uint8_t offset, uint8_t* payload, uint8_t len);
|
||||
|
||||
void beginAppendFragment();
|
||||
void endAppendFragment();
|
||||
|
||||
uint32_t getLastUpdateAll();
|
||||
void setLastUpdateAll(uint32_t lastUpdate);
|
||||
|
||||
@ -47,6 +43,4 @@ private:
|
||||
|
||||
uint8_t _payloadDevInfoSimple[DEV_INFO_SIZE] = {};
|
||||
uint8_t _devInfoSimpleLength = 0;
|
||||
|
||||
SemaphoreHandle_t _xSemaphore;
|
||||
};
|
||||
40
lib/Hoymiles/src/parser/GridProfileParser.cpp
Normal file
40
lib/Hoymiles/src/parser/GridProfileParser.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2023 Thomas Basler and others
|
||||
*/
|
||||
#include "GridProfileParser.h"
|
||||
#include "../Hoymiles.h"
|
||||
#include <cstring>
|
||||
|
||||
GridProfileParser::GridProfileParser()
|
||||
: Parser()
|
||||
{
|
||||
clearBuffer();
|
||||
}
|
||||
|
||||
void GridProfileParser::clearBuffer()
|
||||
{
|
||||
memset(_payloadGridProfile, 0, GRID_PROFILE_SIZE);
|
||||
_gridProfileLength = 0;
|
||||
}
|
||||
|
||||
void GridProfileParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t len)
|
||||
{
|
||||
if (offset + len > GRID_PROFILE_SIZE) {
|
||||
Hoymiles.getMessageOutput()->printf("FATAL: (%s, %d) grid profile packet too large for buffer\r\n", __FILE__, __LINE__);
|
||||
return;
|
||||
}
|
||||
memcpy(&_payloadGridProfile[offset], payload, len);
|
||||
_gridProfileLength += len;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> GridProfileParser::getRawData()
|
||||
{
|
||||
std::vector<uint8_t> ret;
|
||||
HOY_SEMAPHORE_TAKE();
|
||||
for (uint8_t i = 0; i < GRID_PROFILE_SIZE; i++) {
|
||||
ret.push_back(_payloadGridProfile[i]);
|
||||
}
|
||||
HOY_SEMAPHORE_GIVE();
|
||||
return ret;
|
||||
}
|
||||
18
lib/Hoymiles/src/parser/GridProfileParser.h
Normal file
18
lib/Hoymiles/src/parser/GridProfileParser.h
Normal file
@ -0,0 +1,18 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
#include "Parser.h"
|
||||
|
||||
#define GRID_PROFILE_SIZE 141
|
||||
|
||||
class GridProfileParser : public Parser {
|
||||
public:
|
||||
GridProfileParser();
|
||||
void clearBuffer();
|
||||
void appendFragment(uint8_t offset, uint8_t* payload, uint8_t len);
|
||||
|
||||
std::vector<uint8_t> getRawData();
|
||||
|
||||
private:
|
||||
uint8_t _payloadGridProfile[GRID_PROFILE_SIZE] = {};
|
||||
uint8_t _gridProfileLength = 0;
|
||||
};
|
||||
@ -1,9 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2022 Thomas Basler and others
|
||||
* Copyright (C) 2022 - 2023 Thomas Basler and others
|
||||
*/
|
||||
#include "Parser.h"
|
||||
|
||||
Parser::Parser()
|
||||
{
|
||||
_xSemaphore = xSemaphoreCreateMutex();
|
||||
HOY_SEMAPHORE_GIVE(); // release before first use
|
||||
}
|
||||
|
||||
uint32_t Parser::getLastUpdate()
|
||||
{
|
||||
return _lastUpdate;
|
||||
@ -13,3 +19,13 @@ void Parser::setLastUpdate(uint32_t lastUpdate)
|
||||
{
|
||||
_lastUpdate = lastUpdate;
|
||||
}
|
||||
|
||||
void Parser::beginAppendFragment()
|
||||
{
|
||||
HOY_SEMAPHORE_TAKE();
|
||||
}
|
||||
|
||||
void Parser::endAppendFragment()
|
||||
{
|
||||
HOY_SEMAPHORE_GIVE();
|
||||
}
|
||||
@ -1,7 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include <cstdint>
|
||||
|
||||
#define HOY_SEMAPHORE_TAKE() \
|
||||
do { \
|
||||
} while (xSemaphoreTake(_xSemaphore, portMAX_DELAY) != pdPASS)
|
||||
#define HOY_SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore)
|
||||
|
||||
typedef enum {
|
||||
CMD_OK,
|
||||
CMD_NOK,
|
||||
@ -10,9 +16,16 @@ typedef enum {
|
||||
|
||||
class Parser {
|
||||
public:
|
||||
Parser();
|
||||
uint32_t getLastUpdate();
|
||||
void setLastUpdate(uint32_t lastUpdate);
|
||||
|
||||
void beginAppendFragment();
|
||||
void endAppendFragment();
|
||||
|
||||
protected:
|
||||
SemaphoreHandle_t _xSemaphore;
|
||||
|
||||
private:
|
||||
uint32_t _lastUpdate = 0;
|
||||
};
|
||||
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2022 Thomas Basler and others
|
||||
* Copyright (C) 2022 - 2023 Thomas Basler and others
|
||||
*/
|
||||
#include "PowerCommandParser.h"
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
#include "Parser.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
class PowerCommandParser : public Parser {
|
||||
public:
|
||||
|
||||
@ -1,15 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2022 Thomas Basler and others
|
||||
* Copyright (C) 2022 - 2023 Thomas Basler and others
|
||||
*/
|
||||
#include "StatisticsParser.h"
|
||||
#include "../Hoymiles.h"
|
||||
|
||||
#define HOY_SEMAPHORE_TAKE() \
|
||||
do { \
|
||||
} while (xSemaphoreTake(_xSemaphore, portMAX_DELAY) != pdPASS)
|
||||
#define HOY_SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore)
|
||||
|
||||
static float calcYieldTotalCh0(StatisticsParser* iv, uint8_t arg0);
|
||||
static float calcYieldDayCh0(StatisticsParser* iv, uint8_t arg0);
|
||||
static float calcUdcCh(StatisticsParser* iv, uint8_t arg0);
|
||||
@ -33,11 +28,35 @@ const calcFunc_t calcFunctions[] = {
|
||||
{ CALC_IRR_CH, &calcIrradiation }
|
||||
};
|
||||
|
||||
const FieldId_t runtimeFields[] = {
|
||||
FLD_UDC,
|
||||
FLD_IDC,
|
||||
FLD_PDC,
|
||||
FLD_UAC,
|
||||
FLD_IAC,
|
||||
FLD_PAC,
|
||||
FLD_F,
|
||||
FLD_T,
|
||||
FLD_PF,
|
||||
FLD_Q,
|
||||
FLD_UAC_1N,
|
||||
FLD_UAC_2N,
|
||||
FLD_UAC_3N,
|
||||
FLD_UAC_12,
|
||||
FLD_UAC_23,
|
||||
FLD_UAC_31,
|
||||
FLD_IAC_1,
|
||||
FLD_IAC_2,
|
||||
FLD_IAC_3,
|
||||
};
|
||||
|
||||
const FieldId_t dailyProductionFields[] = {
|
||||
FLD_YD,
|
||||
};
|
||||
|
||||
StatisticsParser::StatisticsParser()
|
||||
: Parser()
|
||||
{
|
||||
_xSemaphore = xSemaphoreCreateMutex();
|
||||
HOY_SEMAPHORE_GIVE(); // release before first use
|
||||
clearBuffer();
|
||||
}
|
||||
|
||||
@ -75,16 +94,6 @@ void StatisticsParser::appendFragment(uint8_t offset, uint8_t* payload, uint8_t
|
||||
_statisticLength += len;
|
||||
}
|
||||
|
||||
void StatisticsParser::beginAppendFragment()
|
||||
{
|
||||
HOY_SEMAPHORE_TAKE();
|
||||
}
|
||||
|
||||
void StatisticsParser::endAppendFragment()
|
||||
{
|
||||
HOY_SEMAPHORE_GIVE();
|
||||
}
|
||||
|
||||
const byteAssign_t* StatisticsParser::getAssignmentByChannelField(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId)
|
||||
{
|
||||
for (uint8_t i = 0; i < _byteAssignmentSize; i++) {
|
||||
@ -150,6 +159,47 @@ float StatisticsParser::getChannelFieldValue(ChannelType_t type, ChannelNum_t ch
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool StatisticsParser::setChannelFieldValue(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId, float value)
|
||||
{
|
||||
const byteAssign_t* pos = getAssignmentByChannelField(type, channel, fieldId);
|
||||
fieldSettings_t* setting = getSettingByChannelField(type, channel, fieldId);
|
||||
|
||||
if (pos == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t ptr = pos->start + pos->num - 1;
|
||||
uint8_t end = pos->start;
|
||||
uint16_t div = pos->div;
|
||||
|
||||
if (CMD_CALC == div) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setting != NULL) {
|
||||
value -= setting->offset;
|
||||
}
|
||||
value *= static_cast<float>(div);
|
||||
|
||||
uint32_t val = 0;
|
||||
if (pos->isSigned && pos->num == 2) {
|
||||
val = static_cast<uint32_t>(static_cast<int16_t>(value));
|
||||
} else if (pos->isSigned && pos->num == 4) {
|
||||
val = static_cast<uint32_t>(static_cast<int32_t>(value));
|
||||
} else {
|
||||
val = static_cast<uint32_t>(value);
|
||||
}
|
||||
|
||||
HOY_SEMAPHORE_TAKE();
|
||||
do {
|
||||
_payloadStatistic[ptr] = val;
|
||||
val >>= 8;
|
||||
} while (--ptr >= end);
|
||||
HOY_SEMAPHORE_GIVE();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
String StatisticsParser::getChannelFieldValueString(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId)
|
||||
{
|
||||
return String(
|
||||
@ -253,6 +303,47 @@ uint32_t StatisticsParser::getRxFailureCount()
|
||||
return _rxFailureCount;
|
||||
}
|
||||
|
||||
void StatisticsParser::zeroRuntimeData()
|
||||
{
|
||||
zeroFields(runtimeFields);
|
||||
}
|
||||
|
||||
void StatisticsParser::zeroDailyData()
|
||||
{
|
||||
zeroFields(dailyProductionFields);
|
||||
}
|
||||
|
||||
void StatisticsParser::setLastUpdate(uint32_t lastUpdate)
|
||||
{
|
||||
Parser::setLastUpdate(lastUpdate);
|
||||
setLastUpdateFromInternal(lastUpdate);
|
||||
}
|
||||
|
||||
uint32_t StatisticsParser::getLastUpdateFromInternal()
|
||||
{
|
||||
return _lastUpdateFromInternal;
|
||||
}
|
||||
|
||||
void StatisticsParser::setLastUpdateFromInternal(uint32_t lastUpdate)
|
||||
{
|
||||
_lastUpdateFromInternal = lastUpdate;
|
||||
}
|
||||
|
||||
void StatisticsParser::zeroFields(const FieldId_t* fields)
|
||||
{
|
||||
// Loop all channels
|
||||
for (auto& t : getChannelTypes()) {
|
||||
for (auto& c : getChannelsByType(t)) {
|
||||
for (uint8_t i = 0; i < (sizeof(runtimeFields) / sizeof(runtimeFields[0])); i++) {
|
||||
if (hasChannelFieldValue(t, c, fields[i])) {
|
||||
setChannelFieldValue(t, c, fields[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setLastUpdateFromInternal(millis());
|
||||
}
|
||||
|
||||
static float calcYieldTotalCh0(StatisticsParser* iv, uint8_t arg0)
|
||||
{
|
||||
float yield = 0;
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
#include "Parser.h"
|
||||
#include <Arduino.h>
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
|
||||
@ -107,8 +106,6 @@ public:
|
||||
StatisticsParser();
|
||||
void clearBuffer();
|
||||
void appendFragment(uint8_t offset, uint8_t* payload, uint8_t len);
|
||||
void beginAppendFragment();
|
||||
void endAppendFragment();
|
||||
|
||||
void setByteAssignment(const byteAssign_t* byteAssignment, uint8_t size);
|
||||
|
||||
@ -125,6 +122,8 @@ public:
|
||||
const char* getChannelFieldName(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId);
|
||||
uint8_t getChannelFieldDigits(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId);
|
||||
|
||||
bool setChannelFieldValue(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId, float value);
|
||||
|
||||
float getChannelFieldOffset(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId);
|
||||
void setChannelFieldOffset(ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId, float offset);
|
||||
|
||||
@ -139,7 +138,19 @@ public:
|
||||
void incrementRxFailureCount();
|
||||
uint32_t getRxFailureCount();
|
||||
|
||||
void zeroRuntimeData();
|
||||
void zeroDailyData();
|
||||
|
||||
// Update time when new data from the inverter is received
|
||||
void setLastUpdate(uint32_t lastUpdate);
|
||||
|
||||
// Update time when internal data structure changes (from inverter and by internal manipulation)
|
||||
uint32_t getLastUpdateFromInternal();
|
||||
void setLastUpdateFromInternal(uint32_t lastUpdate);
|
||||
|
||||
private:
|
||||
void zeroFields(const FieldId_t* fields);
|
||||
|
||||
uint8_t _payloadStatistic[STATISTIC_PACKET_SIZE] = {};
|
||||
uint8_t _statisticLength = 0;
|
||||
uint16_t _stringMaxPower[CH_CNT];
|
||||
@ -150,6 +161,5 @@ private:
|
||||
std::list<fieldSettings_t> _fieldSettings;
|
||||
|
||||
uint32_t _rxFailureCount = 0;
|
||||
|
||||
SemaphoreHandle_t _xSemaphore;
|
||||
uint32_t _lastUpdateFromInternal = 0;
|
||||
};
|
||||
@ -1,21 +1,14 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2022 Thomas Basler and others
|
||||
* Copyright (C) 2022 - 2023 Thomas Basler and others
|
||||
*/
|
||||
#include "SystemConfigParaParser.h"
|
||||
#include "../Hoymiles.h"
|
||||
#include <cstring>
|
||||
|
||||
#define HOY_SEMAPHORE_TAKE() \
|
||||
do { \
|
||||
} while (xSemaphoreTake(_xSemaphore, portMAX_DELAY) != pdPASS)
|
||||
#define HOY_SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore)
|
||||
|
||||
SystemConfigParaParser::SystemConfigParaParser()
|
||||
: Parser()
|
||||
{
|
||||
_xSemaphore = xSemaphoreCreateMutex();
|
||||
HOY_SEMAPHORE_GIVE(); // release before first use
|
||||
clearBuffer();
|
||||
}
|
||||
|
||||
@ -35,16 +28,6 @@ void SystemConfigParaParser::appendFragment(uint8_t offset, uint8_t* payload, ui
|
||||
_payloadLength += len;
|
||||
}
|
||||
|
||||
void SystemConfigParaParser::beginAppendFragment()
|
||||
{
|
||||
HOY_SEMAPHORE_TAKE();
|
||||
}
|
||||
|
||||
void SystemConfigParaParser::endAppendFragment()
|
||||
{
|
||||
HOY_SEMAPHORE_GIVE();
|
||||
}
|
||||
|
||||
float SystemConfigParaParser::getLimitPercent()
|
||||
{
|
||||
HOY_SEMAPHORE_TAKE();
|
||||
@ -102,3 +85,8 @@ void SystemConfigParaParser::setLastUpdateRequest(uint32_t lastUpdate)
|
||||
_lastUpdateRequest = lastUpdate;
|
||||
setLastUpdate(lastUpdate);
|
||||
}
|
||||
|
||||
uint8_t SystemConfigParaParser::getExpectedByteCount()
|
||||
{
|
||||
return SYSTEM_CONFIG_PARA_SIZE;
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
#include "Parser.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
#define SYSTEM_CONFIG_PARA_SIZE 16
|
||||
|
||||
@ -10,8 +9,6 @@ public:
|
||||
SystemConfigParaParser();
|
||||
void clearBuffer();
|
||||
void appendFragment(uint8_t offset, uint8_t* payload, uint8_t len);
|
||||
void beginAppendFragment();
|
||||
void endAppendFragment();
|
||||
|
||||
float getLimitPercent();
|
||||
void setLimitPercent(float value);
|
||||
@ -26,6 +23,9 @@ public:
|
||||
uint32_t getLastUpdateRequest();
|
||||
void setLastUpdateRequest(uint32_t lastUpdate);
|
||||
|
||||
// Returns 1 based amount of expected bytes of data
|
||||
uint8_t getExpectedByteCount();
|
||||
|
||||
private:
|
||||
uint8_t _payload[SYSTEM_CONFIG_PARA_SIZE];
|
||||
uint8_t _payloadLength;
|
||||
@ -35,6 +35,4 @@ private:
|
||||
|
||||
uint32_t _lastUpdateCommand = 0;
|
||||
uint32_t _lastUpdateRequest = 0;
|
||||
|
||||
SemaphoreHandle_t _xSemaphore;
|
||||
};
|
||||
@ -33,7 +33,7 @@ build_unflags =
|
||||
lib_deps =
|
||||
https://github.com/yubox-node-org/ESPAsyncWebServer
|
||||
bblanchon/ArduinoJson @ ^6.21.3
|
||||
https://github.com/bertmelis/espMqttClient.git#v1.4.4
|
||||
https://github.com/bertmelis/espMqttClient.git#v1.4.5
|
||||
nrf24/RF24 @ ^1.4.7
|
||||
olikraus/U8g2 @ ^2.35.4
|
||||
buelowp/sunset @ ^1.1.7
|
||||
|
||||
@ -180,12 +180,10 @@ void JkBmsBatteryStats::mqttPublish() const
|
||||
|
||||
void JkBmsBatteryStats::updateFrom(JkBms::DataPointContainer const& dp)
|
||||
{
|
||||
_dataPoints.updateFrom(dp);
|
||||
|
||||
using Label = JkBms::DataPointLabel;
|
||||
|
||||
_manufacturer = "JKBMS";
|
||||
auto oProductId = _dataPoints.get<Label::ProductId>();
|
||||
auto oProductId = dp.get<Label::ProductId>();
|
||||
if (oProductId.has_value()) {
|
||||
_manufacturer = oProductId->c_str();
|
||||
auto pos = oProductId->rfind("JK");
|
||||
@ -194,12 +192,14 @@ void JkBmsBatteryStats::updateFrom(JkBms::DataPointContainer const& dp)
|
||||
}
|
||||
}
|
||||
|
||||
auto oSoCValue = _dataPoints.get<Label::BatterySoCPercent>();
|
||||
auto oSoCValue = dp.get<Label::BatterySoCPercent>();
|
||||
if (oSoCValue.has_value()) {
|
||||
_SoC = *oSoCValue;
|
||||
auto oSoCDataPoint = _dataPoints.getDataPointFor<Label::BatterySoCPercent>();
|
||||
auto oSoCDataPoint = dp.getDataPointFor<Label::BatterySoCPercent>();
|
||||
_lastUpdateSoC = oSoCDataPoint->getTimestamp();
|
||||
}
|
||||
|
||||
_dataPoints.updateFrom(dp);
|
||||
|
||||
_lastUpdate = millis();
|
||||
}
|
||||
|
||||
@ -59,6 +59,7 @@ bool ConfigurationClass::write()
|
||||
mqtt["topic"] = config.Mqtt_Topic;
|
||||
mqtt["retain"] = config.Mqtt_Retain;
|
||||
mqtt["publish_interval"] = config.Mqtt_PublishInterval;
|
||||
mqtt["clean_session"] = config.Mqtt_CleanSession;
|
||||
|
||||
JsonObject mqtt_lwt = mqtt.createNestedObject("lwt");
|
||||
mqtt_lwt["topic"] = config.Mqtt_LwtTopic;
|
||||
@ -111,6 +112,9 @@ bool ConfigurationClass::write()
|
||||
inv["poll_enable_night"] = config.Inverter[i].Poll_Enable_Night;
|
||||
inv["command_enable"] = config.Inverter[i].Command_Enable;
|
||||
inv["command_enable_night"] = config.Inverter[i].Command_Enable_Night;
|
||||
inv["reachable_threshold"] = config.Inverter[i].ReachableThreshold;
|
||||
inv["zero_runtime"] = config.Inverter[i].ZeroRuntimeDataIfUnrechable;
|
||||
inv["zero_day"] = config.Inverter[i].ZeroYieldDayOnMidnight;
|
||||
|
||||
JsonArray channel = inv.createNestedArray("channel");
|
||||
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
||||
@ -278,6 +282,7 @@ bool ConfigurationClass::read()
|
||||
strlcpy(config.Mqtt_Topic, mqtt["topic"] | MQTT_TOPIC, sizeof(config.Mqtt_Topic));
|
||||
config.Mqtt_Retain = mqtt["retain"] | MQTT_RETAIN;
|
||||
config.Mqtt_PublishInterval = mqtt["publish_interval"] | MQTT_PUBLISH_INTERVAL;
|
||||
config.Mqtt_CleanSession = mqtt["clean_session"] | MQTT_CLEAN_SESSION;
|
||||
|
||||
JsonObject mqtt_lwt = mqtt["lwt"];
|
||||
strlcpy(config.Mqtt_LwtTopic, mqtt_lwt["topic"] | MQTT_LWT_TOPIC, sizeof(config.Mqtt_LwtTopic));
|
||||
@ -331,6 +336,9 @@ bool ConfigurationClass::read()
|
||||
config.Inverter[i].Poll_Enable_Night = inv["poll_enable_night"] | true;
|
||||
config.Inverter[i].Command_Enable = inv["command_enable"] | true;
|
||||
config.Inverter[i].Command_Enable_Night = inv["command_enable_night"] | true;
|
||||
config.Inverter[i].ReachableThreshold = inv["reachable_threshold"] | REACHABLE_THRESHOLD;
|
||||
config.Inverter[i].ZeroRuntimeDataIfUnrechable = inv["zero_runtime"] | false;
|
||||
config.Inverter[i].ZeroYieldDayOnMidnight = inv["zero_day"] | false;
|
||||
|
||||
JsonArray channel = inv["channel"];
|
||||
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
||||
|
||||
@ -151,25 +151,25 @@ float DatastoreClass::getTotalDcIrradiation()
|
||||
return _totalDcIrradiation;
|
||||
}
|
||||
|
||||
unsigned int DatastoreClass::getTotalAcYieldTotalDigits()
|
||||
uint32_t DatastoreClass::getTotalAcYieldTotalDigits()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
return _totalAcYieldTotalDigits;
|
||||
}
|
||||
|
||||
unsigned int DatastoreClass::getTotalAcYieldDayDigits()
|
||||
uint32_t DatastoreClass::getTotalAcYieldDayDigits()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
return _totalAcYieldDayDigits;
|
||||
}
|
||||
|
||||
unsigned int DatastoreClass::getTotalAcPowerDigits()
|
||||
uint32_t DatastoreClass::getTotalAcPowerDigits()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
return _totalAcPowerDigits;
|
||||
}
|
||||
|
||||
unsigned int DatastoreClass::getTotalDcPowerDigits()
|
||||
uint32_t DatastoreClass::getTotalDcPowerDigits()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
return _totalDcPowerDigits;
|
||||
|
||||
@ -74,6 +74,9 @@ void InverterSettingsClass::init()
|
||||
config.Inverter[i].Serial);
|
||||
|
||||
if (inv != nullptr) {
|
||||
inv->setReachableThreshold(config.Inverter[i].ReachableThreshold);
|
||||
inv->setZeroValuesIfUnreachable(config.Inverter[i].ZeroRuntimeDataIfUnrechable);
|
||||
inv->setZeroYieldDayOnMidnight(config.Inverter[i].ZeroYieldDayOnMidnight);
|
||||
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
||||
inv->Statistics()->setStringMaxPower(c, config.Inverter[i].channel[c].MaxChannelPower);
|
||||
inv->Statistics()->setChannelFieldOffset(TYPE_DC, static_cast<ChannelNum_t>(c), FLD_YT, config.Inverter[i].channel[c].YieldTotalOffset);
|
||||
|
||||
@ -134,7 +134,7 @@ void MqttHandleHassClass::publishField(std::shared_ptr<InverterAbstract> inv, Ch
|
||||
createDeviceInfo(deviceObj, inv);
|
||||
|
||||
if (Configuration.get().Mqtt_Hass_Expire) {
|
||||
root["exp_aft"] = Hoymiles.getNumInverters() * Configuration.get().Mqtt_PublishInterval * 3;
|
||||
root["exp_aft"] = Hoymiles.getNumInverters() * max<uint32_t>(Hoymiles.PollInterval(), Configuration.get().Mqtt_PublishInterval) * inv->getReachableThreshold();
|
||||
}
|
||||
if (devCls != 0) {
|
||||
root["dev_cla"] = devCls;
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
#define TOPIC_SUB_POWER "power"
|
||||
#define TOPIC_SUB_RESTART "restart"
|
||||
|
||||
#define PUBLISH_MAX_INTERVAL 60000
|
||||
|
||||
MqttHandleInverterClass MqttHandleInverter;
|
||||
|
||||
void MqttHandleInverterClass::init()
|
||||
@ -91,9 +93,9 @@ void MqttHandleInverterClass::loop()
|
||||
MqttSettings.publish(subtopic + "/status/last_update", String(0));
|
||||
}
|
||||
|
||||
uint32_t lastUpdate = inv->Statistics()->getLastUpdate();
|
||||
if (lastUpdate > 0 && lastUpdate != _lastPublishStats[i]) {
|
||||
_lastPublishStats[i] = lastUpdate;
|
||||
uint32_t lastUpdateInternal = inv->Statistics()->getLastUpdateFromInternal();
|
||||
if (inv->Statistics()->getLastUpdate() > 0 && (lastUpdateInternal != _lastPublishStats[i])) {
|
||||
_lastPublishStats[i] = lastUpdateInternal;
|
||||
|
||||
// Loop all channels
|
||||
for (auto& t : inv->Statistics()->getChannelTypes()) {
|
||||
|
||||
@ -130,6 +130,7 @@ void MqttSettingsClass::performConnect()
|
||||
}
|
||||
static_cast<espMqttClientSecure*>(mqttClient)->setWill(willTopic.c_str(), 2, config.Mqtt_Retain, config.Mqtt_LwtValue_Offline);
|
||||
static_cast<espMqttClientSecure*>(mqttClient)->setClientId(clientId.c_str());
|
||||
static_cast<espMqttClientSecure*>(mqttClient)->setCleanSession(config.Mqtt_CleanSession);
|
||||
static_cast<espMqttClientSecure*>(mqttClient)->onConnect(std::bind(&MqttSettingsClass::onMqttConnect, this, _1));
|
||||
static_cast<espMqttClientSecure*>(mqttClient)->onDisconnect(std::bind(&MqttSettingsClass::onMqttDisconnect, this, _1));
|
||||
static_cast<espMqttClientSecure*>(mqttClient)->onMessage(std::bind(&MqttSettingsClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6));
|
||||
@ -138,6 +139,7 @@ void MqttSettingsClass::performConnect()
|
||||
static_cast<espMqttClient*>(mqttClient)->setCredentials(config.Mqtt_Username, config.Mqtt_Password);
|
||||
static_cast<espMqttClient*>(mqttClient)->setWill(willTopic.c_str(), 2, config.Mqtt_Retain, config.Mqtt_LwtValue_Offline);
|
||||
static_cast<espMqttClient*>(mqttClient)->setClientId(clientId.c_str());
|
||||
static_cast<espMqttClient*>(mqttClient)->setCleanSession(config.Mqtt_CleanSession);
|
||||
static_cast<espMqttClient*>(mqttClient)->onConnect(std::bind(&MqttSettingsClass::onMqttConnect, this, _1));
|
||||
static_cast<espMqttClient*>(mqttClient)->onDisconnect(std::bind(&MqttSettingsClass::onMqttDisconnect, this, _1));
|
||||
static_cast<espMqttClient*>(mqttClient)->onMessage(std::bind(&MqttSettingsClass::onMqttMessage, this, _1, _2, _3, _4, _5, _6));
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2022 Thomas Basler and others
|
||||
* Copyright (C) 2022 - 2023 Thomas Basler and others
|
||||
*/
|
||||
#include "NtpSettings.h"
|
||||
#include "Configuration.h"
|
||||
#include <Arduino.h>
|
||||
#include <time.h>
|
||||
|
||||
NtpSettingsClass::NtpSettingsClass()
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "SunPosition.h"
|
||||
#include "Configuration.h"
|
||||
#include "Utils.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
SunPositionClass SunPosition;
|
||||
|
||||
@ -83,7 +84,7 @@ void SunPositionClass::updateSunData()
|
||||
|
||||
_sunriseMinutes = static_cast<int>(sunriseRaw);
|
||||
_sunsetMinutes = static_cast<int>(sunsetRaw);
|
||||
uint minutesPastMidnight = timeinfo.tm_hour * 60 + timeinfo.tm_min;
|
||||
uint32_t minutesPastMidnight = timeinfo.tm_hour * 60 + timeinfo.tm_min;
|
||||
|
||||
_isDayPeriod = (minutesPastMidnight >= _sunriseMinutes) && (minutesPastMidnight < _sunsetMinutes);
|
||||
_isSunsetAvailable = true;
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
uint32_t Utils::getChipId()
|
||||
{
|
||||
uint32_t chipId = 0;
|
||||
for (int i = 0; i < 17; i += 8) {
|
||||
for (uint8_t i = 0; i < 17; i += 8) {
|
||||
chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
|
||||
}
|
||||
return chipId;
|
||||
|
||||
@ -24,6 +24,7 @@ void WebApiClass::init()
|
||||
_webApiDtu.init(&_server);
|
||||
_webApiEventlog.init(&_server);
|
||||
_webApiFirmware.init(&_server);
|
||||
_webApiGridprofile.init(&_server);
|
||||
_webApiInverter.init(&_server);
|
||||
_webApiLimit.init(&_server);
|
||||
_webApiMaintenance.init(&_server);
|
||||
@ -57,6 +58,7 @@ void WebApiClass::loop()
|
||||
_webApiDtu.loop();
|
||||
_webApiEventlog.loop();
|
||||
_webApiFirmware.loop();
|
||||
_webApiGridprofile.loop();
|
||||
_webApiInverter.loop();
|
||||
_webApiLimit.loop();
|
||||
_webApiMaintenance.loop();
|
||||
|
||||
49
src/WebApi_gridprofile.cpp
Normal file
49
src/WebApi_gridprofile.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2022 Thomas Basler and others
|
||||
*/
|
||||
#include "WebApi_gridprofile.h"
|
||||
#include "WebApi.h"
|
||||
#include <AsyncJson.h>
|
||||
#include <Hoymiles.h>
|
||||
|
||||
void WebApiGridProfileClass::init(AsyncWebServer* server)
|
||||
{
|
||||
using std::placeholders::_1;
|
||||
|
||||
_server = server;
|
||||
|
||||
_server->on("/api/gridprofile/status", HTTP_GET, std::bind(&WebApiGridProfileClass::onGridProfileStatus, this, _1));
|
||||
}
|
||||
|
||||
void WebApiGridProfileClass::loop()
|
||||
{
|
||||
}
|
||||
|
||||
void WebApiGridProfileClass::onGridProfileStatus(AsyncWebServerRequest* request)
|
||||
{
|
||||
if (!WebApi.checkCredentialsReadonly(request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 4096);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
uint64_t serial = 0;
|
||||
if (request->hasParam("inv")) {
|
||||
String s = request->getParam("inv")->value();
|
||||
serial = strtoll(s.c_str(), NULL, 16);
|
||||
}
|
||||
|
||||
auto inv = Hoymiles.getInverterBySerial(serial);
|
||||
|
||||
if (inv != nullptr) {
|
||||
auto raw = root.createNestedArray("raw");
|
||||
auto data = inv->GridProfile()->getRawData();
|
||||
|
||||
copyArray(&data[0], data.size(), raw);
|
||||
}
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
||||
@ -7,6 +7,7 @@
|
||||
#include "MqttHandleHass.h"
|
||||
#include "WebApi.h"
|
||||
#include "WebApi_errors.h"
|
||||
#include "defaults.h"
|
||||
#include "helper.h"
|
||||
#include <AsyncJson.h>
|
||||
#include <Hoymiles.h>
|
||||
@ -57,6 +58,9 @@ void WebApiInverterClass::onInverterList(AsyncWebServerRequest* request)
|
||||
obj["poll_enable_night"] = config.Inverter[i].Poll_Enable_Night;
|
||||
obj["command_enable"] = config.Inverter[i].Command_Enable;
|
||||
obj["command_enable_night"] = config.Inverter[i].Command_Enable_Night;
|
||||
obj["reachable_threshold"] = config.Inverter[i].ReachableThreshold;
|
||||
obj["zero_runtime"] = config.Inverter[i].ZeroRuntimeDataIfUnrechable;
|
||||
obj["zero_day"] = config.Inverter[i].ZeroYieldDayOnMidnight;
|
||||
|
||||
auto inv = Hoymiles.getInverterBySerial(config.Inverter[i].Serial);
|
||||
uint8_t max_channels;
|
||||
@ -281,6 +285,9 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
||||
inverter.Poll_Enable_Night = root["poll_enable_night"] | true;
|
||||
inverter.Command_Enable = root["command_enable"] | true;
|
||||
inverter.Command_Enable_Night = root["command_enable_night"] | true;
|
||||
inverter.ReachableThreshold = root["reachable_threshold"] | REACHABLE_THRESHOLD;
|
||||
inverter.ZeroRuntimeDataIfUnrechable = root["zero_runtime"] | false;
|
||||
inverter.ZeroYieldDayOnMidnight = root["zero_day"] | false;
|
||||
|
||||
arrayCount++;
|
||||
}
|
||||
@ -311,6 +318,9 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
||||
if (inv != nullptr) {
|
||||
inv->setEnablePolling(inverter.Poll_Enable);
|
||||
inv->setEnableCommands(inverter.Command_Enable);
|
||||
inv->setReachableThreshold(inverter.ReachableThreshold);
|
||||
inv->setZeroValuesIfUnreachable(inverter.ZeroRuntimeDataIfUnrechable);
|
||||
inv->setZeroYieldDayOnMidnight(inverter.ZeroYieldDayOnMidnight);
|
||||
for (uint8_t c = 0; c < INV_MAX_CHAN_COUNT; c++) {
|
||||
inv->Statistics()->setStringMaxPower(c, inverter.channel[c].MaxChannelPower);
|
||||
inv->Statistics()->setChannelFieldOffset(TYPE_DC, static_cast<ChannelNum_t>(c), FLD_YT, inverter.channel[c].YieldTotalOffset);
|
||||
|
||||
@ -54,6 +54,7 @@ void WebApiMqttClass::onMqttStatus(AsyncWebServerRequest* request)
|
||||
root["mqtt_client_cert_info"] = getTlsCertInfo(config.Mqtt_ClientCert);
|
||||
root["mqtt_lwt_topic"] = String(config.Mqtt_Topic) + config.Mqtt_LwtTopic;
|
||||
root["mqtt_publish_interval"] = config.Mqtt_PublishInterval;
|
||||
root["mqtt_clean_session"] = config.Mqtt_CleanSession;
|
||||
root["mqtt_hass_enabled"] = config.Mqtt_Hass_Enabled;
|
||||
root["mqtt_hass_expire"] = config.Mqtt_Hass_Expire;
|
||||
root["mqtt_hass_retain"] = config.Mqtt_Hass_Retain;
|
||||
@ -91,6 +92,7 @@ void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request)
|
||||
root["mqtt_lwt_online"] = config.Mqtt_LwtValue_Online;
|
||||
root["mqtt_lwt_offline"] = config.Mqtt_LwtValue_Offline;
|
||||
root["mqtt_publish_interval"] = config.Mqtt_PublishInterval;
|
||||
root["mqtt_clean_session"] = config.Mqtt_CleanSession;
|
||||
root["mqtt_hass_enabled"] = config.Mqtt_Hass_Enabled;
|
||||
root["mqtt_hass_expire"] = config.Mqtt_Hass_Expire;
|
||||
root["mqtt_hass_retain"] = config.Mqtt_Hass_Retain;
|
||||
@ -156,6 +158,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
||||
&& root.containsKey("mqtt_lwt_online")
|
||||
&& root.containsKey("mqtt_lwt_offline")
|
||||
&& root.containsKey("mqtt_publish_interval")
|
||||
&& root.containsKey("mqtt_clean_session")
|
||||
&& root.containsKey("mqtt_hass_enabled")
|
||||
&& root.containsKey("mqtt_hass_expire")
|
||||
&& root.containsKey("mqtt_hass_retain")
|
||||
@ -321,6 +324,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
||||
strlcpy(config.Mqtt_LwtValue_Online, root["mqtt_lwt_online"].as<String>().c_str(), sizeof(config.Mqtt_LwtValue_Online));
|
||||
strlcpy(config.Mqtt_LwtValue_Offline, root["mqtt_lwt_offline"].as<String>().c_str(), sizeof(config.Mqtt_LwtValue_Offline));
|
||||
config.Mqtt_PublishInterval = root["mqtt_publish_interval"].as<uint32_t>();
|
||||
config.Mqtt_CleanSession = root["mqtt_clean_session"].as<bool>();
|
||||
config.Mqtt_Hass_Enabled = root["mqtt_hass_enabled"].as<bool>();
|
||||
config.Mqtt_Hass_Expire = root["mqtt_hass_expire"].as<bool>();
|
||||
config.Mqtt_Hass_Retain = root["mqtt_hass_retain"].as<bool>();
|
||||
|
||||
@ -66,6 +66,11 @@ void WebApiWsLiveClass::loop()
|
||||
if (millis() - _lastWsPublish > (10 * 1000) || (maxTimeStamp != _newestInverterTimestamp)) {
|
||||
|
||||
try {
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
DynamicJsonDocument root(4096 * INV_MAX_COUNT);
|
||||
JsonVariant var = root;
|
||||
generateJsonResponse(var);
|
||||
|
||||
String buffer;
|
||||
// free JsonDocument as soon as possible
|
||||
{
|
||||
@ -152,6 +157,7 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
|
||||
addField(chanTypeObj, i, inv, t, c, FLD_EFF);
|
||||
if (t == TYPE_DC && inv->Statistics()->getStringMaxPower(c) > 0) {
|
||||
addField(chanTypeObj, i, inv, t, c, FLD_IRR);
|
||||
chanTypeObj[String(c)][inv->Statistics()->getChannelFieldName(t, c, FLD_IRR)]["max"] = inv->Statistics()->getStringMaxPower(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -231,13 +237,9 @@ void WebApiWsLiveClass::addTotalField(JsonObject& root, String name, float value
|
||||
void WebApiWsLiveClass::onWebsocketEvent(AsyncWebSocket* server, AsyncWebSocketClient* client, AwsEventType type, void* arg, uint8_t* data, size_t len)
|
||||
{
|
||||
if (type == WS_EVT_CONNECT) {
|
||||
char str[64];
|
||||
snprintf(str, sizeof(str), "Websocket: [%s][%u] connect", server->url(), client->id());
|
||||
MessageOutput.println(str);
|
||||
MessageOutput.printf("Websocket: [%s][%u] connect\r\n", server->url(), client->id());
|
||||
} else if (type == WS_EVT_DISCONNECT) {
|
||||
char str[64];
|
||||
snprintf(str, sizeof(str), "Websocket: [%s][%u] disconnect", server->url(), client->id());
|
||||
MessageOutput.println(str);
|
||||
MessageOutput.printf("Websocket: [%s][%u] disconnect\r\n", server->url(), client->id());
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,7 +250,8 @@ void WebApiWsLiveClass::onLivedataStatus(AsyncWebServerRequest* request)
|
||||
}
|
||||
|
||||
try {
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 40960U);
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 4096 * INV_MAX_COUNT);
|
||||
JsonVariant root = response->getRoot();
|
||||
|
||||
generateJsonResponse(root);
|
||||
|
||||
@ -18,29 +18,29 @@
|
||||
"sortablejs": "^1.15.0",
|
||||
"spark-md5": "^3.0.2",
|
||||
"vue": "^3.3.4",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-i18n": "^9.4.0",
|
||||
"vue-router": "^4.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@intlify/unplugin-vue-i18n": "^0.12.3",
|
||||
"@intlify/unplugin-vue-i18n": "^1.2.0",
|
||||
"@rushstack/eslint-patch": "^1.3.3",
|
||||
"@tsconfig/node18": "^18.2.1",
|
||||
"@tsconfig/node18": "^18.2.2",
|
||||
"@types/bootstrap": "^5.2.6",
|
||||
"@types/node": "^20.5.7",
|
||||
"@types/node": "^20.6.0",
|
||||
"@types/sortablejs": "^1.15.2",
|
||||
"@types/spark-md5": "^3.0.2",
|
||||
"@vitejs/plugin-vue": "^4.3.3",
|
||||
"@vue/eslint-config-typescript": "^11.0.3",
|
||||
"@vitejs/plugin-vue": "^4.3.4",
|
||||
"@vue/eslint-config-typescript": "^12.0.0",
|
||||
"@vue/tsconfig": "^0.4.0",
|
||||
"eslint": "^8.48.0",
|
||||
"eslint": "^8.49.0",
|
||||
"eslint-plugin-vue": "^9.17.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"sass": "^1.64.2",
|
||||
"terser": "^5.19.2",
|
||||
"sass": "^1.66.1",
|
||||
"terser": "^5.19.4",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^4.4.9",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-css-injected-by-js": "^3.3.0",
|
||||
"vue-tsc": "^1.8.8"
|
||||
"vue-tsc": "^1.8.11"
|
||||
}
|
||||
}
|
||||
|
||||
50
webapp/src/components/GridProfile.vue
Normal file
50
webapp/src/components/GridProfile.vue
Normal file
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<BootstrapAlert :show="!hasValidData">
|
||||
<h4 class="alert-heading">
|
||||
<BIconInfoSquare class="fs-2" /> {{ $t('gridprofile.NoInfo') }}
|
||||
</h4>{{ $t('gridprofile.NoInfoLong') }}
|
||||
</BootstrapAlert>
|
||||
|
||||
<template v-if="hasValidData">
|
||||
<BootstrapAlert :show="true" variant="danger">
|
||||
<h4 class="info-heading">
|
||||
<BIconInfoSquare class="fs-2" /> {{ $t('gridprofile.GridprofileSupport') }}
|
||||
</h4><div v-html="$t('gridprofile.GridprofileSupportLong')"></div>
|
||||
</BootstrapAlert>
|
||||
<samp >
|
||||
{{ rawContent() }}
|
||||
</samp>
|
||||
</template>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import BootstrapAlert from '@/components/BootstrapAlert.vue';
|
||||
import type { GridProfileStatus } from "@/types/GridProfileStatus";
|
||||
import { BIconInfoSquare } from 'bootstrap-icons-vue';
|
||||
import { defineComponent, type PropType } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BootstrapAlert,
|
||||
BIconInfoSquare,
|
||||
},
|
||||
props: {
|
||||
gridProfileList: { type: Object as PropType<GridProfileStatus>, required: true },
|
||||
},
|
||||
computed: {
|
||||
rawContent() {
|
||||
return () => {
|
||||
return this.gridProfileList.raw.map(function (x) {
|
||||
let y = x.toString(16); // to hex
|
||||
y = ("00" + y).substr(-2); // zero-pad to 2-digits
|
||||
return y
|
||||
}).join(' ');
|
||||
}
|
||||
},
|
||||
hasValidData() {
|
||||
return this.gridProfileList.raw.reduce((sum, x) => sum + x, 0) > 0;
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -134,7 +134,9 @@
|
||||
"Failure": "Fehlgeschlagen",
|
||||
"Pending": "Ausstehend",
|
||||
"Ok": "Ok",
|
||||
"Unknown": "Unbekannt"
|
||||
"Unknown": "Unbekannt",
|
||||
"ShowGridProfile": "Zeige Grid Profil",
|
||||
"GridProfile": "Grid Profil"
|
||||
},
|
||||
"vedirecthome": {
|
||||
"SerialNumber": "Seriennummer: ",
|
||||
@ -192,6 +194,12 @@
|
||||
"HardwarePartNumber": "Hardware-Teilenummer",
|
||||
"HardwareVersion": "Hardware-Version"
|
||||
},
|
||||
"gridprofile": {
|
||||
"NoInfo": "@:devinfo.NoInfo",
|
||||
"NoInfoLong": "@:devinfo.NoInfoLong",
|
||||
"GridprofileSupport": "Unterstütze die Entwicklung",
|
||||
"GridprofileSupportLong": "Weitere Informationen sind <a href=\"https://github.com/tbnobody/OpenDTU/wiki/Grid-Profile-Parser\" target=\"_blank\">hier</a> zu finden."
|
||||
},
|
||||
"systeminfo": {
|
||||
"SystemInfo": "System Informationen",
|
||||
"VersionError": "Fehler beim Abrufen von Versionsinformationen",
|
||||
@ -308,6 +316,7 @@
|
||||
"BaseTopic": "Basis Topic",
|
||||
"PublishInterval": "Veröffentlichungsintervall",
|
||||
"Seconds": "{sec} Sekunden",
|
||||
"CleanSession": "CleanSession Flag",
|
||||
"Retain": "Retain",
|
||||
"Tls": "TLS",
|
||||
"RootCertifcateInfo": "Root CA-Zertifikat-Informationen",
|
||||
@ -474,6 +483,7 @@
|
||||
"BaseTopicHint": "Basis-Topic, wird allen veröffentlichten Themen vorangestellt (z.B. inverter/)",
|
||||
"PublishInterval": "Veröffentlichungsintervall:",
|
||||
"Seconds": "Sekunden",
|
||||
"CleanSession": "CleanSession Flag aktivieren",
|
||||
"EnableRetain": "Retain Flag aktivieren",
|
||||
"EnableTls": "TLS aktivieren",
|
||||
"RootCa": "CA-Root-Zertifikat (Standard Letsencrypt):",
|
||||
@ -614,6 +624,9 @@
|
||||
"SaveOrder": "Reihenfolge speichern",
|
||||
"DeleteInverter": "Wechselrichter löschen",
|
||||
"EditInverter": "Wechselrichter bearbeiten",
|
||||
"General": "Allgemein",
|
||||
"String": "String",
|
||||
"Advanced": "Erweitert",
|
||||
"InverterSerial": "Wechselrichter Seriennummer:",
|
||||
"InverterName": "Wechselrichter Name:",
|
||||
"InverterNameHint": "Hier kann ein eigener Namen für den Wechselrichter angeben werden.",
|
||||
@ -629,6 +642,12 @@
|
||||
"StringYtOffset": "Ertragsversatz String {num}:",
|
||||
"StringYtOffsetHint": "Dieser Offset wird beim Auslesen des Gesamtertragswertes des Wechselrichters angewendet. Damit kann der Gesamtertrag des Wechselrichters auf Null gesetzt werden, wenn ein gebrauchter Wechselrichter verwendet wird.",
|
||||
"InverterHint": "*) Geben Sie die W<sub>p</sub> des Ports ein, um die Einstrahlung zu errechnen.",
|
||||
"ReachableThreshold": "Erreichbarkeit Schwellenwert:",
|
||||
"ReachableThresholdHint": "Legt fest, wie viele Anfragen fehlschlagen dürfen, bis der Wechselrichter als unerreichbar eingestuft wird.",
|
||||
"ZeroRuntime": "Nulle Laufzeit Daten",
|
||||
"ZeroRuntimeHint": "Nulle Laufzeit Daten (keine Ertragsdaten), wenn der Wechselrichter nicht erreichbar ist.",
|
||||
"ZeroDay": "Nulle Tagesertrag um Mitternacht",
|
||||
"ZeroDayHint": "Das funktioniert nur wenn der Wechselrichter nicht erreichbar ist. Wenn Daten aus dem Wechselrichter gelesen werden, werden deren Werte verwendet. (Ein Reset erfolgt nur beim Neustarten)",
|
||||
"Cancel": "@:maintenancereboot.Cancel",
|
||||
"Save": "@:dtuadmin.Save",
|
||||
"DeleteMsg": "Soll der Wechselrichter \"{name}\" mit der Seriennummer {serial} wirklich gelöscht werden?",
|
||||
|
||||
@ -134,7 +134,9 @@
|
||||
"Failure": "Failure",
|
||||
"Pending": "Pending",
|
||||
"Ok": "Ok",
|
||||
"Unknown": "Unknown"
|
||||
"Unknown": "Unknown",
|
||||
"ShowGridProfile": "Show Grid Profile",
|
||||
"GridProfile": "Grid Profile"
|
||||
},
|
||||
"vedirecthome": {
|
||||
"SerialNumber": "Serial Number: ",
|
||||
@ -192,6 +194,12 @@
|
||||
"HardwarePartNumber": "Hardware Part Number",
|
||||
"HardwareVersion": "Hardware Version"
|
||||
},
|
||||
"gridprofile": {
|
||||
"NoInfo": "@:devinfo.NoInfo",
|
||||
"NoInfoLong": "@:devinfo.NoInfoLong",
|
||||
"GridprofileSupport": "Support the development",
|
||||
"GridprofileSupportLong": "Please see <a href=\"https://github.com/tbnobody/OpenDTU/wiki/Grid-Profile-Parser\" target=\"_blank\">here</a> for further information."
|
||||
},
|
||||
"systeminfo": {
|
||||
"SystemInfo": "System Info",
|
||||
"VersionError": "Error fetching version information",
|
||||
@ -310,6 +318,7 @@
|
||||
"BaseTopic": "Base Topic",
|
||||
"PublishInterval": "Publish Interval",
|
||||
"Seconds": "{sec} seconds",
|
||||
"CleanSession": "CleanSession flag",
|
||||
"Retain": "Retain",
|
||||
"Tls": "TLS",
|
||||
"RootCertifcateInfo": "Root CA Certifcate Info",
|
||||
@ -476,6 +485,7 @@
|
||||
"BaseTopicHint": "Base topic, will be prepend to all published topics (e.g. inverter/)",
|
||||
"PublishInterval": "Publish Interval:",
|
||||
"Seconds": "seconds",
|
||||
"CleanSession": "Enable CleanSession flag",
|
||||
"EnableRetain": "Enable Retain Flag",
|
||||
"EnableTls": "Enable TLS",
|
||||
"RootCa": "CA-Root-Certificate (default Letsencrypt):",
|
||||
@ -623,6 +633,9 @@
|
||||
"SaveOrder": "Save order",
|
||||
"DeleteInverter": "Delete inverter",
|
||||
"EditInverter": "Edit inverter",
|
||||
"General": "General",
|
||||
"String": "String",
|
||||
"Advanced": "Advanced",
|
||||
"InverterSerial": "Inverter Serial:",
|
||||
"InverterName": "Inverter Name:",
|
||||
"InverterNameHint": "Here you can specify a custom name for your inverter.",
|
||||
@ -638,6 +651,12 @@
|
||||
"StringYtOffset": "Yield total offset string {num}:",
|
||||
"StringYtOffsetHint": "This offset is applied the read yield total value from the inverter. This can be used to set the yield total of the inverter to zero if a used inverter is used. But you can still try polling data.",
|
||||
"InverterHint": "*) Enter the W<sub>p</sub> of the channel to calculate irradiation.",
|
||||
"ReachableThreshold": "Reachable Threshold:",
|
||||
"ReachableThresholdHint": "Defines how many requests are allowed to fail until the inverter is treated is not reachable.",
|
||||
"ZeroRuntime": "Zero runtime data",
|
||||
"ZeroRuntimeHint": "Zero runtime data (no yield data) if inverter becomes unreachable.",
|
||||
"ZeroDay": "Zero daily yield at midnight",
|
||||
"ZeroDayHint": "This only works if the inverter is unreachable. If data is read from the inverter, it's values will be used. (Reset only occours on power cycle)",
|
||||
"Cancel": "@:maintenancereboot.Cancel",
|
||||
"Save": "@:dtuadmin.Save",
|
||||
"DeleteMsg": "Are you sure you want to delete the inverter \"{name}\" with serial number {serial}?",
|
||||
|
||||
@ -134,7 +134,9 @@
|
||||
"Failure": "Échec",
|
||||
"Pending": "En attente",
|
||||
"Ok": "OK",
|
||||
"Unknown": "Inconnu"
|
||||
"Unknown": "Inconnu",
|
||||
"ShowGridProfile": "Show Grid Profile",
|
||||
"GridProfile": "Grid Profile"
|
||||
},
|
||||
"vedirecthome": {
|
||||
"SerialNumber": "Serial Number: ",
|
||||
@ -192,6 +194,12 @@
|
||||
"HardwarePartNumber": "Numéro d'article matériel",
|
||||
"HardwareVersion": "Version du matériel"
|
||||
},
|
||||
"gridprofile": {
|
||||
"NoInfo": "@:devinfo.NoInfo",
|
||||
"NoInfoLong": "@:devinfo.NoInfoLong",
|
||||
"GridprofileSupport": "Support the development",
|
||||
"GridprofileSupportLong": "Please see <a href=\"https://github.com/tbnobody/OpenDTU/wiki/Grid-Profile-Parser\" target=\"_blank\">here</a> for further information."
|
||||
},
|
||||
"systeminfo": {
|
||||
"SystemInfo": "Informations sur le système",
|
||||
"VersionError": "Erreur de récupération des informations de version",
|
||||
@ -308,6 +316,7 @@
|
||||
"BaseTopic": "Sujet de base",
|
||||
"PublishInterval": "Intervalle de publication",
|
||||
"Seconds": "{sec} secondes",
|
||||
"CleanSession": "CleanSession Flag",
|
||||
"Retain": "Conserver",
|
||||
"Tls": "TLS",
|
||||
"RootCertifcateInfo": "Informations sur le certificat de l'autorité de certification racine",
|
||||
@ -474,6 +483,7 @@
|
||||
"BaseTopicHint": "Sujet de base, qui sera ajouté en préambule à tous les sujets publiés (par exemple, inverter/).",
|
||||
"PublishInterval": "Intervalle de publication",
|
||||
"Seconds": "secondes",
|
||||
"CleanSession": "Enable CleanSession flag",
|
||||
"EnableRetain": "Activation du maintien",
|
||||
"EnableTls": "Activer le TLS",
|
||||
"RootCa": "Certificat CA-Root (par défaut Letsencrypt)",
|
||||
@ -521,6 +531,9 @@
|
||||
"SaveOrder": "Save order",
|
||||
"DeleteInverter": "Supprimer l'onduleur",
|
||||
"EditInverter": "Modifier l'onduleur",
|
||||
"General": "Général",
|
||||
"String": "Ligne",
|
||||
"Advanced": "Advanced",
|
||||
"InverterSerial": "Numéro de série de l'onduleur",
|
||||
"InverterName": "Nom de l'onduleur :",
|
||||
"InverterNameHint": "Ici, vous pouvez spécifier un nom personnalisé pour votre onduleur.",
|
||||
@ -536,6 +549,12 @@
|
||||
"StringYtOffset": "Décalage du rendement total de la ligne {num} :",
|
||||
"StringYtOffsetHint": "Ce décalage est appliqué à la valeur de rendement total lue sur le variateur. Il peut être utilisé pour mettre le rendement total du variateur à zéro si un variateur usagé est utilisé.",
|
||||
"InverterHint": "*) Entrez le W<sub>p</sub> du canal pour calculer l'irradiation.",
|
||||
"ReachableThreshold": "Reachable Threshold:",
|
||||
"ReachableThresholdHint": "Defines how many requests are allowed to fail until the inverter is treated is not reachable.",
|
||||
"ZeroRuntime": "Zero runtime data",
|
||||
"ZeroRuntimeHint": "Zero runtime data (no yield data) if inverter becomes unreachable.",
|
||||
"ZeroDay": "Zero daily yield at midnight",
|
||||
"ZeroDayHint": "This only works if the inverter is unreachable. If data is read from the inverter, it's values will be used. (Reset only occours on power cycle)",
|
||||
"Cancel": "@:maintenancereboot.Cancel",
|
||||
"Save": "@:dtuadmin.Save",
|
||||
"DeleteMsg": "Êtes-vous sûr de vouloir supprimer l'onduleur \"{name}\" avec le numéro de série \"{serial}\" ?",
|
||||
|
||||
3
webapp/src/types/GridProfileStatus.ts
Normal file
3
webapp/src/types/GridProfileStatus.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export interface GridProfileStatus {
|
||||
raw: Array<number>;
|
||||
}
|
||||
@ -2,6 +2,7 @@ export interface ValueObject {
|
||||
v: number; // value
|
||||
u: string; // unit
|
||||
d: number; // digits
|
||||
max: number;
|
||||
}
|
||||
|
||||
export interface InverterStatistics {
|
||||
|
||||
@ -7,6 +7,7 @@ export interface MqttConfig {
|
||||
mqtt_password: string;
|
||||
mqtt_topic: string;
|
||||
mqtt_publish_interval: number;
|
||||
mqtt_clean_session: boolean;
|
||||
mqtt_retain: boolean;
|
||||
mqtt_tls: boolean;
|
||||
mqtt_root_ca_cert: string;
|
||||
|
||||
@ -6,6 +6,7 @@ export interface MqttStatus {
|
||||
mqtt_username: string;
|
||||
mqtt_topic: string;
|
||||
mqtt_publish_interval: number;
|
||||
mqtt_clean_session: boolean;
|
||||
mqtt_retain: boolean;
|
||||
mqtt_tls: boolean;
|
||||
mqtt_root_ca_cert_info: string;
|
||||
|
||||
@ -78,6 +78,14 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="btn-group me-2" role="group">
|
||||
<button type="button" class="btn btn-sm btn-info"
|
||||
@click="onShowGridProfile(inverter.serial)" v-tooltip :title="$t('home.ShowGridProfile')">
|
||||
<BIconOutlet style="font-size:24px;" />
|
||||
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="btn-group" role="group">
|
||||
<button v-if="inverter.events >= 0" type="button"
|
||||
class="btn btn-sm btn-secondary position-relative"
|
||||
@ -98,7 +106,7 @@
|
||||
<template v-for="channel in Object.keys(chanType.obj).sort().reverse().map(x=>+x)" :key="channel">
|
||||
<template v-if="(chanType.name != 'DC') ||
|
||||
(chanType.name == 'DC' && getSumIrridiation(inverter) == 0) ||
|
||||
(chanType.name == 'DC' && getSumIrridiation(inverter) > 0 && chanType.obj[channel].Irradiation?.v || 0 > 0)
|
||||
(chanType.name == 'DC' && getSumIrridiation(inverter) > 0 && chanType.obj[channel].Irradiation?.max || 0 > 0)
|
||||
">
|
||||
<div class="col">
|
||||
<InverterChannelInfo :channelData="chanType.obj[channel]"
|
||||
@ -170,6 +178,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="gridProfileView" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">{{ $t('home.GridProfile') }}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="text-center" v-if="gridProfileLoading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">{{ $t('home.Loading') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<GridProfile v-if="!gridProfileLoading" :gridProfileList="gridProfileList" />
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @click="onHideGridProfile"
|
||||
data-bs-dismiss="modal">{{ $t('home.Close') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="limitSettingView" ref="limitSettingView" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
@ -324,6 +357,7 @@ import BasePage from '@/components/BasePage.vue';
|
||||
import BootstrapAlert from '@/components/BootstrapAlert.vue';
|
||||
import DevInfo from '@/components/DevInfo.vue';
|
||||
import EventLog from '@/components/EventLog.vue';
|
||||
import GridProfile from '@/components/GridProfile.vue';
|
||||
import HintView from '@/components/HintView.vue';
|
||||
import InverterChannelInfo from "@/components/InverterChannelInfo.vue";
|
||||
import InverterTotalInfo from '@/components/InverterTotalInfo.vue';
|
||||
@ -332,6 +366,7 @@ import HuaweiView from '@/components/HuaweiView.vue'
|
||||
import BatteryView from '@/components/BatteryView.vue'
|
||||
import type { DevInfoStatus } from '@/types/DevInfoStatus';
|
||||
import type { EventlogItems } from '@/types/EventlogStatus';
|
||||
import type { GridProfileStatus } from '@/types/GridProfileStatus';
|
||||
import type { LimitConfig } from '@/types/LimitConfig';
|
||||
import type { LimitStatus } from '@/types/LimitStatus';
|
||||
import type { Inverter, LiveData } from '@/types/LiveDataStatus';
|
||||
@ -343,6 +378,7 @@ import {
|
||||
BIconCpu,
|
||||
BIconExclamationCircleFill,
|
||||
BIconJournalText,
|
||||
BIconOutlet,
|
||||
BIconPower,
|
||||
BIconSpeedometer,
|
||||
BIconToggleOff,
|
||||
@ -357,6 +393,7 @@ export default defineComponent({
|
||||
BootstrapAlert,
|
||||
DevInfo,
|
||||
EventLog,
|
||||
GridProfile,
|
||||
HintView,
|
||||
InverterChannelInfo,
|
||||
InverterTotalInfo,
|
||||
@ -365,6 +402,7 @@ export default defineComponent({
|
||||
BIconCpu,
|
||||
BIconExclamationCircleFill,
|
||||
BIconJournalText,
|
||||
BIconOutlet,
|
||||
BIconPower,
|
||||
BIconSpeedometer,
|
||||
BIconToggleOff,
|
||||
@ -390,6 +428,9 @@ export default defineComponent({
|
||||
devInfoView: {} as bootstrap.Modal,
|
||||
devInfoList: {} as DevInfoStatus,
|
||||
devInfoLoading: true,
|
||||
gridProfileView: {} as bootstrap.Modal,
|
||||
gridProfileList: {} as GridProfileStatus,
|
||||
gridProfileLoading: true,
|
||||
|
||||
limitSettingView: {} as bootstrap.Modal,
|
||||
limitSettingLoading: true,
|
||||
@ -430,6 +471,7 @@ export default defineComponent({
|
||||
mounted() {
|
||||
this.eventLogView = new bootstrap.Modal('#eventView');
|
||||
this.devInfoView = new bootstrap.Modal('#devInfoView');
|
||||
this.gridProfileView = new bootstrap.Modal('#gridProfileView');
|
||||
this.limitSettingView = new bootstrap.Modal('#limitSettingView');
|
||||
this.powerSettingView = new bootstrap.Modal('#powerSettingView');
|
||||
|
||||
@ -494,9 +536,15 @@ export default defineComponent({
|
||||
|
||||
this.socket.onmessage = (event) => {
|
||||
console.log(event);
|
||||
if (event.data != "{}") {
|
||||
this.liveData = JSON.parse(event.data);
|
||||
this.dataLoading = false;
|
||||
this.heartCheck(); // Reset heartbeat detection
|
||||
} else {
|
||||
// Sometimes it does not recover automatically so have to force a reconnect
|
||||
this.closeSocket();
|
||||
this.heartCheck(10); // Reconnect faster
|
||||
}
|
||||
};
|
||||
|
||||
this.socket.onopen = function (event) {
|
||||
@ -519,7 +567,7 @@ export default defineComponent({
|
||||
}, 1000);
|
||||
},
|
||||
// Send heartbeat packets regularly * 59s Send a heartbeat
|
||||
heartCheck() {
|
||||
heartCheck(duration: number = 59) {
|
||||
this.heartInterval && clearTimeout(this.heartInterval);
|
||||
this.heartInterval = setInterval(() => {
|
||||
if (this.socket.readyState === 1) {
|
||||
@ -528,7 +576,7 @@ export default defineComponent({
|
||||
} else {
|
||||
this.initSocket(); // Breakpoint reconnection 5 Time
|
||||
}
|
||||
}, 59 * 1000);
|
||||
}, duration * 1000);
|
||||
},
|
||||
/** To break off websocket Connect */
|
||||
closeSocket() {
|
||||
@ -565,6 +613,20 @@ export default defineComponent({
|
||||
|
||||
this.devInfoView.show();
|
||||
},
|
||||
onHideGridProfile() {
|
||||
this.devInfoView.hide();
|
||||
},
|
||||
onShowGridProfile(serial: number) {
|
||||
this.gridProfileLoading = true;
|
||||
fetch("/api/gridprofile/status?inv=" + serial, { headers: authHeader() })
|
||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||
.then((data) => {
|
||||
this.gridProfileList = data;
|
||||
this.gridProfileLoading = false;
|
||||
});
|
||||
|
||||
this.gridProfileView.show();
|
||||
},
|
||||
onHideLimitSettings() {
|
||||
this.showAlertLimit = false;
|
||||
},
|
||||
@ -689,7 +751,7 @@ export default defineComponent({
|
||||
getSumIrridiation(inv: Inverter): number {
|
||||
let total = 0;
|
||||
Object.keys(inv.DC).forEach((key) => {
|
||||
total += inv.DC[key as unknown as number].Irradiation?.v || 0;
|
||||
total += inv.DC[key as unknown as number].Irradiation?.max || 0;
|
||||
});
|
||||
return total;
|
||||
}
|
||||
|
||||
@ -80,6 +80,20 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form>
|
||||
<nav>
|
||||
<div class="nav nav-tabs" id="nav-tab" role="tablist">
|
||||
<button class="nav-link active" id="nav-general-tab" data-bs-toggle="tab" data-bs-target="#nav-general"
|
||||
type="button" role="tab" aria-controls="nav-general" aria-selected="true">{{
|
||||
$t('inverteradmin.General')
|
||||
}}</button>
|
||||
<button class="nav-link" id="nav-string-tab" data-bs-toggle="tab" data-bs-target="#nav-string"
|
||||
type="button" role="tab" aria-controls="nav-string">{{ $t('inverteradmin.String') }}</button>
|
||||
<button class="nav-link" id="nav-advanced-tab" data-bs-toggle="tab" data-bs-target="#nav-advanced"
|
||||
type="button" role="tab" aria-controls="nav-advanced">{{ $t('inverteradmin.Advanced') }}</button>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="tab-content" id="nav-tabContent">
|
||||
<div class="tab-pane fade show active" id="nav-general" role="tabpanel" aria-labelledby="nav-general-tab" tabindex="0">
|
||||
<div class="mb-3">
|
||||
<label for="inverter-serial" class="col-form-label">
|
||||
{{ $t('inverteradmin.InverterSerial') }}
|
||||
@ -108,7 +122,9 @@
|
||||
<div class="alert alert-secondary mt-3" role="alert" v-html="$t('inverteradmin.StatusHint')"></div>
|
||||
</CardElement>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade show" id="nav-string" role="tabpanel" aria-labelledby="nav-string-tab" tabindex="0">
|
||||
<div v-for="(ch, index) in selectedInverterData.channel" :key="`${index}`">
|
||||
<div class="row g-2">
|
||||
<div class="col-md">
|
||||
@ -159,6 +175,25 @@
|
||||
</div>
|
||||
<div :id="`inverter-customizer`" class="form-text" v-html="$t('inverteradmin.InverterHint')">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade show" id="nav-advanced" role="tabpanel" aria-labelledby="nav-advanced-tab" tabindex="0">
|
||||
<InputElement :label="$t('inverteradmin.ReachableThreshold')"
|
||||
v-model="selectedInverterData.reachable_threshold"
|
||||
type="number" min="1" max="100"
|
||||
:tooltip="$t('inverteradmin.ReachableThresholdHint')" wide />
|
||||
|
||||
<InputElement :label="$t('inverteradmin.ZeroRuntime')"
|
||||
v-model="selectedInverterData.zero_runtime"
|
||||
type="checkbox"
|
||||
:tooltip="$t('inverteradmin.ZeroRuntimeHint')" wide/>
|
||||
|
||||
<InputElement :label="$t('inverteradmin.ZeroDay')"
|
||||
v-model="selectedInverterData.zero_day"
|
||||
type="checkbox"
|
||||
:tooltip="$t('inverteradmin.ZeroDayHint')" wide/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
@ -231,6 +266,9 @@ declare interface Inverter {
|
||||
poll_enable_night: boolean;
|
||||
command_enable: boolean;
|
||||
command_enable_night: boolean;
|
||||
reachable_threshold: number;
|
||||
zero_runtime: boolean;
|
||||
zero_day: boolean;
|
||||
channel: Array<Channel>;
|
||||
}
|
||||
|
||||
|
||||
@ -53,6 +53,10 @@
|
||||
type="number" min="5" max="86400"
|
||||
:postfix="$t('mqttadmin.Seconds')"/>
|
||||
|
||||
<InputElement :label="$t('mqttadmin.CleanSession')"
|
||||
v-model="mqttConfigList.mqtt_clean_session"
|
||||
type="checkbox"/>
|
||||
|
||||
<InputElement :label="$t('mqttadmin.EnableRetain')"
|
||||
v-model="mqttConfigList.mqtt_retain"
|
||||
type="checkbox"/>
|
||||
|
||||
@ -36,6 +36,12 @@
|
||||
<th>{{ $t('mqttinfo.PublishInterval') }}</th>
|
||||
<td>{{ $t('mqttinfo.Seconds', { sec: mqttDataList.mqtt_publish_interval }) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $t('mqttinfo.CleanSession') }}</th>
|
||||
<td>
|
||||
<StatusBadge :status="mqttDataList.mqtt_clean_session" true_text="mqttinfo.Enabled" false_text="mqttinfo.Disabled" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ $t('mqttinfo.Retain') }}</th>
|
||||
<td>
|
||||
|
||||
547
webapp/yarn.lock
547
webapp/yarn.lock
@ -141,10 +141,10 @@
|
||||
dependencies:
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@eslint-community/regexpp@^4.4.0":
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.4.0.tgz#3e61c564fcd6b921cb789838631c5ee44df09403"
|
||||
integrity sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==
|
||||
"@eslint-community/regexpp@^4.5.1":
|
||||
version "4.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.8.1.tgz#8c4bb756cc2aa7eaf13cfa5e69c83afb3260c20c"
|
||||
integrity sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==
|
||||
|
||||
"@eslint-community/regexpp@^4.6.1":
|
||||
version "4.6.2"
|
||||
@ -166,15 +166,15 @@
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/js@8.48.0":
|
||||
version "8.48.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.48.0.tgz#642633964e217905436033a2bd08bf322849b7fb"
|
||||
integrity sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==
|
||||
"@eslint/js@8.49.0":
|
||||
version "8.49.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.49.0.tgz#86f79756004a97fa4df866835093f1df3d03c333"
|
||||
integrity sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==
|
||||
|
||||
"@humanwhocodes/config-array@^0.11.10":
|
||||
version "0.11.10"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2"
|
||||
integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==
|
||||
"@humanwhocodes/config-array@^0.11.11":
|
||||
version "0.11.11"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.11.tgz#88a04c570dbbc7dd943e4712429c3df09bc32844"
|
||||
integrity sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==
|
||||
dependencies:
|
||||
"@humanwhocodes/object-schema" "^1.2.1"
|
||||
debug "^4.1.1"
|
||||
@ -190,72 +190,50 @@
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
|
||||
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
|
||||
|
||||
"@intlify/bundle-utils@^7.0.2":
|
||||
version "7.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/bundle-utils/-/bundle-utils-7.0.2.tgz#2c92a4d815d97a160c2c662a9951a790296e2fd2"
|
||||
integrity sha512-8wbx9xhbawBFTE5LPTECiK26RRqrNS31jyWSur72ZXZZ4it5jiZTcG6eUJlNirr4+jXYio2DGY299JsGVT4cpw==
|
||||
"@intlify/bundle-utils@^7.3.0":
|
||||
version "7.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/bundle-utils/-/bundle-utils-7.3.0.tgz#11048e8aeede313f7492cefcf412359bd31eed76"
|
||||
integrity sha512-lcnfsLA5Dyd3TbvfoLS0ejLr1vAJYyT6VRYtE4LGNexy1ZD/GEcbXrC33fI9oQp7t2hDlHbCn2o4BBVgXaJFqg==
|
||||
dependencies:
|
||||
"@intlify/message-compiler" "9.3.0-beta.24"
|
||||
"@intlify/shared" "9.3.0-beta.24"
|
||||
"@intlify/message-compiler" "^9.4.0"
|
||||
"@intlify/shared" "^9.4.0"
|
||||
acorn "^8.8.2"
|
||||
escodegen "^2.0.0"
|
||||
estree-walker "^2.0.2"
|
||||
jsonc-eslint-parser "^1.0.1"
|
||||
jsonc-eslint-parser "^2.3.0"
|
||||
magic-string "^0.30.0"
|
||||
mlly "^1.2.0"
|
||||
source-map-js "^1.0.1"
|
||||
yaml-eslint-parser "^0.3.2"
|
||||
yaml-eslint-parser "^1.2.2"
|
||||
|
||||
"@intlify/core-base@9.2.2":
|
||||
version "9.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.2.2.tgz#5353369b05cc9fe35cab95fe20afeb8a4481f939"
|
||||
integrity sha512-JjUpQtNfn+joMbrXvpR4hTF8iJQ2sEFzzK3KIESOx+f+uwIjgw20igOyaIdhfsVVBCds8ZM64MoeNSx+PHQMkA==
|
||||
"@intlify/core-base@9.4.0":
|
||||
version "9.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.4.0.tgz#a99a89f1263ab0f4d2889b49629bfbbf4f238d85"
|
||||
integrity sha512-bIvtuEjLES35l39R0OccYbmr/fatSr4VSRThhouvFc05mnoAZyJGgj3st1iLaHGlFTmvd507uww1427o56r36Q==
|
||||
dependencies:
|
||||
"@intlify/devtools-if" "9.2.2"
|
||||
"@intlify/message-compiler" "9.2.2"
|
||||
"@intlify/shared" "9.2.2"
|
||||
"@intlify/vue-devtools" "9.2.2"
|
||||
"@intlify/message-compiler" "9.4.0"
|
||||
"@intlify/shared" "9.4.0"
|
||||
|
||||
"@intlify/devtools-if@9.2.2":
|
||||
version "9.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/devtools-if/-/devtools-if-9.2.2.tgz#b13d9ac4b4e2fe6d2e7daa556517a8061fe8bd39"
|
||||
integrity sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==
|
||||
"@intlify/message-compiler@9.4.0", "@intlify/message-compiler@^9.4.0":
|
||||
version "9.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.4.0.tgz#c11fceb4cc07dfe6a4b3066ca6e9a9e44e897f23"
|
||||
integrity sha512-EdjqOH3bQqEjZcUOwo90wuW4ZuFr41FDxVni6WNKS0V0myKgwz9EuvLDcnEbjJMIX8vKAWPjWfnSTt5fMwKHLA==
|
||||
dependencies:
|
||||
"@intlify/shared" "9.2.2"
|
||||
|
||||
"@intlify/message-compiler@9.2.2":
|
||||
version "9.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.2.2.tgz#e42ab6939b8ae5b3d21faf6a44045667a18bba1c"
|
||||
integrity sha512-IUrQW7byAKN2fMBe8z6sK6riG1pue95e5jfokn8hA5Q3Bqy4MBJ5lJAofUsawQJYHeoPJ7svMDyBaVJ4d0GTtA==
|
||||
dependencies:
|
||||
"@intlify/shared" "9.2.2"
|
||||
source-map "0.6.1"
|
||||
|
||||
"@intlify/message-compiler@9.3.0-beta.24":
|
||||
version "9.3.0-beta.24"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.3.0-beta.24.tgz#0f1e2cbc4ac223be67b61dbaaac0d9eac8b0decb"
|
||||
integrity sha512-prhHATkgp0mpPqoVgiAtLmUc1JMvs8fMH6w53AVEBn+VF87dLhzanfmWY5FoZWORG51ag54gBDBOoM/VFv3m3A==
|
||||
dependencies:
|
||||
"@intlify/shared" "9.3.0-beta.24"
|
||||
"@intlify/shared" "9.4.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
"@intlify/shared@9.2.2":
|
||||
version "9.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.2.2.tgz#5011be9ca2b4ab86f8660739286e2707f9abb4a5"
|
||||
integrity sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==
|
||||
"@intlify/shared@9.4.0", "@intlify/shared@^9.4.0":
|
||||
version "9.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.4.0.tgz#4a78d462fc82433db900981e12eb5b1aae3d6085"
|
||||
integrity sha512-AFqymip2kToqA0B6KZPg5jSrdcVHoli9t/VhGKE2iiMq9utFuMoGdDC/JOCIZgwxo6aXAk86QyU2XtzEoMuZ6A==
|
||||
|
||||
"@intlify/shared@9.3.0-beta.24":
|
||||
version "9.3.0-beta.24"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.3.0-beta.24.tgz#23e08af9fc904fe3ef896786f9e659da6bb567b5"
|
||||
integrity sha512-AKxJ8s7eKIQWkNaf4wyyoLRwf4puCuQgjSChlDJm5JBEt6T8HGgnYTJLRXu6LD/JACn3Qwu6hM/XRX1c9yvjmQ==
|
||||
|
||||
"@intlify/unplugin-vue-i18n@^0.12.3":
|
||||
version "0.12.3"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/unplugin-vue-i18n/-/unplugin-vue-i18n-0.12.3.tgz#fae7d92d3e7bfe9e710fb332b28d22e0f8d999f2"
|
||||
integrity sha512-0riPtSfTM58JmGNMmJho/aHD2z3K24BESYAmkLvKlo61/LbaPvnjYU1DbSbJEm6bSjE2oEjUj+di3QaYxXei/w==
|
||||
"@intlify/unplugin-vue-i18n@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/unplugin-vue-i18n/-/unplugin-vue-i18n-1.2.0.tgz#ca4ac742140f1eaf4668c9530db5db23069eb604"
|
||||
integrity sha512-AzjlMZKj9DG10ICDR2VWjfJudHJ1XK2GNSHxw+VmOUYpUm4S0L/a7OAdvgnuY7S4plk1VnPdT4YilpZk+uQcqg==
|
||||
dependencies:
|
||||
"@intlify/bundle-utils" "^7.0.2"
|
||||
"@intlify/shared" "9.3.0-beta.24"
|
||||
"@intlify/bundle-utils" "^7.3.0"
|
||||
"@intlify/shared" "^9.4.0"
|
||||
"@rollup/pluginutils" "^5.0.2"
|
||||
"@vue/compiler-sfc" "^3.2.47"
|
||||
debug "^4.3.3"
|
||||
@ -267,14 +245,6 @@
|
||||
source-map-js "^1.0.2"
|
||||
unplugin "^1.1.0"
|
||||
|
||||
"@intlify/vue-devtools@9.2.2":
|
||||
version "9.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@intlify/vue-devtools/-/vue-devtools-9.2.2.tgz#b95701556daf7ebb3a2d45aa3ae9e6415aed8317"
|
||||
integrity sha512-+dUyqyCHWHb/UcvY1MlIpO87munedm3Gn6E9WWYdWrMuYLcoIoOEVDWSS8xSwtlPU+kA+MEQTP6Q1iI/ocusJg==
|
||||
dependencies:
|
||||
"@intlify/core-base" "9.2.2"
|
||||
"@intlify/shared" "9.2.2"
|
||||
|
||||
"@jridgewell/gen-mapping@^0.3.0":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
|
||||
@ -360,10 +330,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.3.3.tgz#16ab6c727d8c2020a5b6e4a176a243ecd88d8d69"
|
||||
integrity sha512-0xd7qez0AQ+MbHatZTlI1gu5vkG8r7MYRUJAHPAHJBmGLs16zpkrpAVLvjQKQOqaXPDUBwOiJzNc00znHSCVBw==
|
||||
|
||||
"@tsconfig/node18@^18.2.1":
|
||||
version "18.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@tsconfig/node18/-/node18-18.2.1.tgz#ebf5e6b8d94e9de072e712bc197d6441a325ed61"
|
||||
integrity sha512-RDDZFuofwkcKpl8Vpj5wFbY+H53xOtqK7ckEL1sXsbPwvKwDdjQf3LkHbtt9sxIHn9nWIEwkmCwBRZ6z5TKU2A==
|
||||
"@tsconfig/node18@^18.2.2":
|
||||
version "18.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@tsconfig/node18/-/node18-18.2.2.tgz#81fb16ecff0d400b1cbadbf76713b50f331029ce"
|
||||
integrity sha512-d6McJeGsuoRlwWZmVIeE8CUA27lu6jLjvv1JzqmpsytOYYbVi1tHZEnwCNVOXnj4pyLvneZlFlpXUK+X9wBWyw==
|
||||
|
||||
"@types/bootstrap@^5.2.6":
|
||||
version "5.2.6"
|
||||
@ -377,20 +347,20 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2"
|
||||
integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==
|
||||
|
||||
"@types/json-schema@^7.0.9":
|
||||
version "7.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
|
||||
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
|
||||
"@types/json-schema@^7.0.12":
|
||||
version "7.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
|
||||
integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==
|
||||
|
||||
"@types/node@^20.5.7":
|
||||
version "20.5.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.7.tgz#4b8ecac87fbefbc92f431d09c30e176fc0a7c377"
|
||||
integrity sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==
|
||||
"@types/node@^20.6.0":
|
||||
version "20.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.0.tgz#9d7daa855d33d4efec8aea88cd66db1c2f0ebe16"
|
||||
integrity sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==
|
||||
|
||||
"@types/semver@^7.3.12":
|
||||
version "7.3.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91"
|
||||
integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==
|
||||
"@types/semver@^7.5.0":
|
||||
version "7.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.1.tgz#0480eeb7221eb9bc398ad7432c9d7e14b1a5a367"
|
||||
integrity sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==
|
||||
|
||||
"@types/sortablejs@^1.15.2":
|
||||
version "1.15.2"
|
||||
@ -402,94 +372,95 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/spark-md5/-/spark-md5-3.0.2.tgz#da2e8a778a20335fc4f40b6471c4b0d86b70da55"
|
||||
integrity sha512-82E/lVRaqelV9qmRzzJ1PKTpyrpnT7mwdneKNJB9hUtypZDMggloDfFUCIqRRx3lYRxteCwXSq9c+W71Vf0QnQ==
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^5.59.1":
|
||||
version "5.59.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.1.tgz#9b09ee1541bff1d2cebdcb87e7ce4a4003acde08"
|
||||
integrity sha512-AVi0uazY5quFB9hlp2Xv+ogpfpk77xzsgsIEWyVS7uK/c7MZ5tw7ZPbapa0SbfkqE0fsAMkz5UwtgMLVk2BQAg==
|
||||
"@typescript-eslint/eslint-plugin@^6.7.0":
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.0.tgz#ed2a38867190f8a688af85ad7c8a74670b8b3675"
|
||||
integrity sha512-gUqtknHm0TDs1LhY12K2NA3Rmlmp88jK9Tx8vGZMfHeNMLE3GH2e9TRub+y+SOjuYgtOmok+wt1AyDPZqxbNag==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.4.0"
|
||||
"@typescript-eslint/scope-manager" "5.59.1"
|
||||
"@typescript-eslint/type-utils" "5.59.1"
|
||||
"@typescript-eslint/utils" "5.59.1"
|
||||
"@eslint-community/regexpp" "^4.5.1"
|
||||
"@typescript-eslint/scope-manager" "6.7.0"
|
||||
"@typescript-eslint/type-utils" "6.7.0"
|
||||
"@typescript-eslint/utils" "6.7.0"
|
||||
"@typescript-eslint/visitor-keys" "6.7.0"
|
||||
debug "^4.3.4"
|
||||
grapheme-splitter "^1.0.4"
|
||||
ignore "^5.2.0"
|
||||
natural-compare-lite "^1.4.0"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
graphemer "^1.4.0"
|
||||
ignore "^5.2.4"
|
||||
natural-compare "^1.4.0"
|
||||
semver "^7.5.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
|
||||
"@typescript-eslint/parser@^5.59.1":
|
||||
version "5.59.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.59.1.tgz#73c2c12127c5c1182d2e5b71a8fa2a85d215cbb4"
|
||||
integrity sha512-nzjFAN8WEu6yPRDizIFyzAfgK7nybPodMNFGNH0M9tei2gYnYszRDqVA0xlnRjkl7Hkx2vYrEdb6fP2a21cG1g==
|
||||
"@typescript-eslint/parser@^6.7.0":
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.7.0.tgz#332fe9c7ecf6783d3250b4c8a960bd4af0995807"
|
||||
integrity sha512-jZKYwqNpNm5kzPVP5z1JXAuxjtl2uG+5NpaMocFPTNC2EdYIgbXIPImObOkhbONxtFTTdoZstLZefbaK+wXZng==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.59.1"
|
||||
"@typescript-eslint/types" "5.59.1"
|
||||
"@typescript-eslint/typescript-estree" "5.59.1"
|
||||
"@typescript-eslint/scope-manager" "6.7.0"
|
||||
"@typescript-eslint/types" "6.7.0"
|
||||
"@typescript-eslint/typescript-estree" "6.7.0"
|
||||
"@typescript-eslint/visitor-keys" "6.7.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.59.1":
|
||||
version "5.59.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.1.tgz#8a20222719cebc5198618a5d44113705b51fd7fe"
|
||||
integrity sha512-mau0waO5frJctPuAzcxiNWqJR5Z8V0190FTSqRw1Q4Euop6+zTwHAf8YIXNwDOT29tyUDrQ65jSg9aTU/H0omA==
|
||||
"@typescript-eslint/scope-manager@6.7.0":
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.7.0.tgz#6b3c22187976e2bf5ed0dc0d9095f1f2cbd1d106"
|
||||
integrity sha512-lAT1Uau20lQyjoLUQ5FUMSX/dS07qux9rYd5FGzKz/Kf8W8ccuvMyldb8hadHdK/qOI7aikvQWqulnEq2nCEYA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.59.1"
|
||||
"@typescript-eslint/visitor-keys" "5.59.1"
|
||||
"@typescript-eslint/types" "6.7.0"
|
||||
"@typescript-eslint/visitor-keys" "6.7.0"
|
||||
|
||||
"@typescript-eslint/type-utils@5.59.1":
|
||||
version "5.59.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.59.1.tgz#63981d61684fd24eda2f9f08c0a47ecb000a2111"
|
||||
integrity sha512-ZMWQ+Oh82jWqWzvM3xU+9y5U7MEMVv6GLioM3R5NJk6uvP47kZ7YvlgSHJ7ERD6bOY7Q4uxWm25c76HKEwIjZw==
|
||||
"@typescript-eslint/type-utils@6.7.0":
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.7.0.tgz#21a013d4c7f96255f5e64ac59fb41301d1e052ba"
|
||||
integrity sha512-f/QabJgDAlpSz3qduCyQT0Fw7hHpmhOzY/Rv6zO3yO+HVIdPfIWhrQoAyG+uZVtWAIS85zAyzgAFfyEr+MgBpg==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "5.59.1"
|
||||
"@typescript-eslint/utils" "5.59.1"
|
||||
"@typescript-eslint/typescript-estree" "6.7.0"
|
||||
"@typescript-eslint/utils" "6.7.0"
|
||||
debug "^4.3.4"
|
||||
tsutils "^3.21.0"
|
||||
ts-api-utils "^1.0.1"
|
||||
|
||||
"@typescript-eslint/types@5.59.1":
|
||||
version "5.59.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.1.tgz#03f3fedd1c044cb336ebc34cc7855f121991f41d"
|
||||
integrity sha512-dg0ICB+RZwHlysIy/Dh1SP+gnXNzwd/KS0JprD3Lmgmdq+dJAJnUPe1gNG34p0U19HvRlGX733d/KqscrGC1Pg==
|
||||
"@typescript-eslint/types@6.7.0":
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.7.0.tgz#8de8ba9cafadc38e89003fe303e219c9250089ae"
|
||||
integrity sha512-ihPfvOp7pOcN/ysoj0RpBPOx3HQTJTrIN8UZK+WFd3/iDeFHHqeyYxa4hQk4rMhsz9H9mXpR61IzwlBVGXtl9Q==
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.59.1":
|
||||
version "5.59.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.1.tgz#4aa546d27fd0d477c618f0ca00b483f0ec84c43c"
|
||||
integrity sha512-lYLBBOCsFltFy7XVqzX0Ju+Lh3WPIAWxYpmH/Q7ZoqzbscLiCW00LeYCdsUnnfnj29/s1WovXKh2gwCoinHNGA==
|
||||
"@typescript-eslint/typescript-estree@6.7.0":
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.0.tgz#20ce2801733bd46f02cc0f141f5b63fbbf2afb63"
|
||||
integrity sha512-dPvkXj3n6e9yd/0LfojNU8VMUGHWiLuBZvbM6V6QYD+2qxqInE7J+J/ieY2iGwR9ivf/R/haWGkIj04WVUeiSQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.59.1"
|
||||
"@typescript-eslint/visitor-keys" "5.59.1"
|
||||
"@typescript-eslint/types" "6.7.0"
|
||||
"@typescript-eslint/visitor-keys" "6.7.0"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
is-glob "^4.0.3"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
semver "^7.5.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
|
||||
"@typescript-eslint/utils@5.59.1":
|
||||
version "5.59.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.1.tgz#d89fc758ad23d2157cfae53f0b429bdf15db9473"
|
||||
integrity sha512-MkTe7FE+K1/GxZkP5gRj3rCztg45bEhsd8HYjczBuYm+qFHP5vtZmjx3B0yUCDotceQ4sHgTyz60Ycl225njmA==
|
||||
"@typescript-eslint/utils@6.7.0":
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.7.0.tgz#61b6f1f1b82ad529abfcee074d21764e880886fb"
|
||||
integrity sha512-MfCq3cM0vh2slSikQYqK2Gq52gvOhe57vD2RM3V4gQRZYX4rDPnKLu5p6cm89+LJiGlwEXU8hkYxhqqEC/V3qA==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.2.0"
|
||||
"@types/json-schema" "^7.0.9"
|
||||
"@types/semver" "^7.3.12"
|
||||
"@typescript-eslint/scope-manager" "5.59.1"
|
||||
"@typescript-eslint/types" "5.59.1"
|
||||
"@typescript-eslint/typescript-estree" "5.59.1"
|
||||
eslint-scope "^5.1.1"
|
||||
semver "^7.3.7"
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
"@types/json-schema" "^7.0.12"
|
||||
"@types/semver" "^7.5.0"
|
||||
"@typescript-eslint/scope-manager" "6.7.0"
|
||||
"@typescript-eslint/types" "6.7.0"
|
||||
"@typescript-eslint/typescript-estree" "6.7.0"
|
||||
semver "^7.5.4"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.59.1":
|
||||
version "5.59.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.1.tgz#0d96c36efb6560d7fb8eb85de10442c10d8f6058"
|
||||
integrity sha512-6waEYwBTCWryx0VJmP7JaM4FpipLsFl9CvYf2foAE8Qh/Y0s+bxWysciwOs0LTBED4JCaNxTZ5rGadB14M6dwA==
|
||||
"@typescript-eslint/visitor-keys@6.7.0":
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.0.tgz#34140ac76dfb6316d17012e4469acf3366ad3f44"
|
||||
integrity sha512-/C1RVgKFDmGMcVGeD8HjKv2bd72oI1KxQDeY8uc66gw9R0OK0eMq48cA+jv9/2Ag6cdrsUGySm1yzYmfz0hxwQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.59.1"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
"@typescript-eslint/types" "6.7.0"
|
||||
eslint-visitor-keys "^3.4.1"
|
||||
|
||||
"@vitejs/plugin-vue@^4.3.3":
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-4.3.3.tgz#3b2337f64495f95cfea5b1497d2d3f4a0b3382b2"
|
||||
integrity sha512-ssxyhIAZqB0TrpUg6R0cBpCuMk9jTIlO1GNSKKQD6S8VjnXi6JXKfUXjSsxey9IwQiaRGsO1WnW9Rkl1L6AJVw==
|
||||
"@vitejs/plugin-vue@^4.3.4":
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-4.3.4.tgz#a289dff38e01949fe7be581d5542cabaeb961dec"
|
||||
integrity sha512-ciXNIHKPriERBisHFBvnTbfKa6r9SAesOYXeGDzgegcvy9Q4xdScSHAmKbNT0M3O0S9LKhIf5/G+UYG4NnnzYw==
|
||||
|
||||
"@volar/language-core@1.10.0", "@volar/language-core@~1.10.0":
|
||||
version "1.10.0"
|
||||
@ -614,29 +585,24 @@
|
||||
"@vue/compiler-dom" "3.3.4"
|
||||
"@vue/shared" "3.3.4"
|
||||
|
||||
"@vue/devtools-api@^6.2.1":
|
||||
version "6.4.5"
|
||||
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.4.5.tgz#d54e844c1adbb1e677c81c665ecef1a2b4bb8380"
|
||||
integrity sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ==
|
||||
|
||||
"@vue/devtools-api@^6.5.0":
|
||||
version "6.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz#98b99425edee70b4c992692628fa1ea2c1e57d07"
|
||||
integrity sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==
|
||||
|
||||
"@vue/eslint-config-typescript@^11.0.3":
|
||||
version "11.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@vue/eslint-config-typescript/-/eslint-config-typescript-11.0.3.tgz#c720efa657d102cd2945bc54b4a79f35d57f6307"
|
||||
integrity sha512-dkt6W0PX6H/4Xuxg/BlFj5xHvksjpSlVjtkQCpaYJBIEuKj2hOVU7r+TIe+ysCwRYFz/lGqvklntRkCAibsbPw==
|
||||
"@vue/eslint-config-typescript@^12.0.0":
|
||||
version "12.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@vue/eslint-config-typescript/-/eslint-config-typescript-12.0.0.tgz#0ce22d97af5e4155f3f2e7b21a48cfde8a6f3365"
|
||||
integrity sha512-StxLFet2Qe97T8+7L8pGlhYBBr8Eg05LPuTDVopQV6il+SK6qqom59BA/rcFipUef2jD8P2X44Vd8tMFytfvlg==
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin" "^5.59.1"
|
||||
"@typescript-eslint/parser" "^5.59.1"
|
||||
vue-eslint-parser "^9.1.1"
|
||||
"@typescript-eslint/eslint-plugin" "^6.7.0"
|
||||
"@typescript-eslint/parser" "^6.7.0"
|
||||
vue-eslint-parser "^9.3.1"
|
||||
|
||||
"@vue/language-core@1.8.8":
|
||||
version "1.8.8"
|
||||
resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-1.8.8.tgz#5a8aa8363f4dfacdfcd7808a9926744d7c310ae6"
|
||||
integrity sha512-i4KMTuPazf48yMdYoebTkgSOJdFraE4pQf0B+FTOFkbB+6hAfjrSou/UmYWRsWyZV6r4Rc6DDZdI39CJwL0rWw==
|
||||
"@vue/language-core@1.8.11":
|
||||
version "1.8.11"
|
||||
resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-1.8.11.tgz#d10cc6f8f32e30991e0430f0d91db9416dc2e9a6"
|
||||
integrity sha512-+MZOBGqGwfld6hpo0DB47x8eNM0dNqk15ZdfOhj19CpvuYuOWCeVdOEGZunKDyo3QLkTn3kLOSysJzg7FDOQBA==
|
||||
dependencies:
|
||||
"@volar/language-core" "~1.10.0"
|
||||
"@volar/source-map" "~1.10.0"
|
||||
@ -728,23 +694,23 @@
|
||||
resolved "https://registry.yarnpkg.com/@vue/tsconfig/-/tsconfig-0.4.0.tgz#f01e2f6089b5098136fb084a0dd0cdd4533b72b0"
|
||||
integrity sha512-CPuIReonid9+zOG/CGTT05FXrPYATEqoDGNrEaqS4hwcw5BUNM2FguC0mOwJD4Jr16UpRVl9N0pY3P+srIbqmg==
|
||||
|
||||
"@vue/typescript@1.8.8":
|
||||
version "1.8.8"
|
||||
resolved "https://registry.yarnpkg.com/@vue/typescript/-/typescript-1.8.8.tgz#8efb375d448862134492a044f4e96afada547500"
|
||||
integrity sha512-jUnmMB6egu5wl342eaUH236v8tdcEPXXkPgj+eI/F6JwW/lb+yAU6U07ZbQ3MVabZRlupIlPESB7ajgAGixhow==
|
||||
"@vue/typescript@1.8.11":
|
||||
version "1.8.11"
|
||||
resolved "https://registry.yarnpkg.com/@vue/typescript/-/typescript-1.8.11.tgz#b2de6760a0e6d829a5328cd0123b1763ce3e66ef"
|
||||
integrity sha512-skUmMDiPUUtu1flPmf2YybF+PX8IzBtMioQOaNn6Ck/RhdrPJGj1AX/7s3Buf9G6ln+/KHR1XQuti/FFxw5XVA==
|
||||
dependencies:
|
||||
"@volar/typescript" "~1.10.0"
|
||||
"@vue/language-core" "1.8.8"
|
||||
"@vue/language-core" "1.8.11"
|
||||
|
||||
acorn-jsx@^5.2.0, acorn-jsx@^5.3.2:
|
||||
acorn-jsx@^5.3.2:
|
||||
version "5.3.2"
|
||||
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
|
||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||
|
||||
acorn@^7.1.1, acorn@^7.4.1:
|
||||
version "7.4.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||
acorn@^8.5.0, acorn@^8.9.0:
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
|
||||
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
|
||||
|
||||
acorn@^8.8.0:
|
||||
version "8.8.0"
|
||||
@ -756,11 +722,6 @@ acorn@^8.8.2:
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
|
||||
integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
|
||||
|
||||
acorn@^8.9.0:
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5"
|
||||
integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==
|
||||
|
||||
ajv@^6.12.4:
|
||||
version "6.12.6"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
||||
@ -1117,14 +1078,6 @@ eslint-plugin-vue@^9.17.0:
|
||||
vue-eslint-parser "^9.3.1"
|
||||
xml-name-validator "^4.0.0"
|
||||
|
||||
eslint-scope@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
|
||||
integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
|
||||
dependencies:
|
||||
esrecurse "^4.3.0"
|
||||
estraverse "^4.1.1"
|
||||
|
||||
eslint-scope@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
|
||||
@ -1141,17 +1094,10 @@ eslint-scope@^7.2.2:
|
||||
esrecurse "^4.3.0"
|
||||
estraverse "^5.2.0"
|
||||
|
||||
eslint-utils@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
|
||||
integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
|
||||
dependencies:
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
|
||||
eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
|
||||
integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
|
||||
eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.4.3:
|
||||
version "3.4.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint-visitor-keys@^3.3.0:
|
||||
version "3.3.0"
|
||||
@ -1163,21 +1109,16 @@ eslint-visitor-keys@^3.4.1:
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994"
|
||||
integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==
|
||||
|
||||
eslint-visitor-keys@^3.4.3:
|
||||
version "3.4.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint@^8.48.0:
|
||||
version "8.48.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.48.0.tgz#bf9998ba520063907ba7bfe4c480dc8be03c2155"
|
||||
integrity sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==
|
||||
eslint@^8.49.0:
|
||||
version "8.49.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.49.0.tgz#09d80a89bdb4edee2efcf6964623af1054bf6d42"
|
||||
integrity sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.2.0"
|
||||
"@eslint-community/regexpp" "^4.6.1"
|
||||
"@eslint/eslintrc" "^2.1.2"
|
||||
"@eslint/js" "8.48.0"
|
||||
"@humanwhocodes/config-array" "^0.11.10"
|
||||
"@eslint/js" "8.49.0"
|
||||
"@humanwhocodes/config-array" "^0.11.11"
|
||||
"@humanwhocodes/module-importer" "^1.0.1"
|
||||
"@nodelib/fs.walk" "^1.2.8"
|
||||
ajv "^6.12.4"
|
||||
@ -1211,14 +1152,14 @@ eslint@^8.48.0:
|
||||
strip-ansi "^6.0.1"
|
||||
text-table "^0.2.0"
|
||||
|
||||
espree@^6.0.0:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a"
|
||||
integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==
|
||||
espree@^9.0.0, espree@^9.6.1:
|
||||
version "9.6.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
|
||||
integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==
|
||||
dependencies:
|
||||
acorn "^7.1.1"
|
||||
acorn-jsx "^5.2.0"
|
||||
eslint-visitor-keys "^1.1.0"
|
||||
acorn "^8.9.0"
|
||||
acorn-jsx "^5.3.2"
|
||||
eslint-visitor-keys "^3.4.1"
|
||||
|
||||
espree@^9.3.1:
|
||||
version "9.3.3"
|
||||
@ -1238,15 +1179,6 @@ espree@^9.6.0:
|
||||
acorn-jsx "^5.3.2"
|
||||
eslint-visitor-keys "^3.4.1"
|
||||
|
||||
espree@^9.6.1:
|
||||
version "9.6.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
|
||||
integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==
|
||||
dependencies:
|
||||
acorn "^8.9.0"
|
||||
acorn-jsx "^5.3.2"
|
||||
eslint-visitor-keys "^3.4.1"
|
||||
|
||||
esprima@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
|
||||
@ -1273,11 +1205,6 @@ esrecurse@^4.3.0:
|
||||
dependencies:
|
||||
estraverse "^5.2.0"
|
||||
|
||||
estraverse@^4.1.1:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
|
||||
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
|
||||
|
||||
estraverse@^5.1.0, estraverse@^5.2.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
|
||||
@ -1478,11 +1405,6 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0:
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
|
||||
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
|
||||
|
||||
grapheme-splitter@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
|
||||
integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
|
||||
|
||||
graphemer@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
|
||||
@ -1544,6 +1466,11 @@ ignore@^5.2.0:
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
|
||||
integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
|
||||
|
||||
ignore@^5.2.4:
|
||||
version "5.2.4"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
|
||||
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
|
||||
|
||||
immutable@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef"
|
||||
@ -1732,16 +1659,15 @@ json5@^2.2.3:
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||
|
||||
jsonc-eslint-parser@^1.0.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-eslint-parser/-/jsonc-eslint-parser-1.4.1.tgz#8cbe99f6f5199acbc5a823c4c0b6135411027fa6"
|
||||
integrity sha512-hXBrvsR1rdjmB2kQmUjf1rEIa+TqHBGMge8pwi++C+Si1ad7EjZrJcpgwym+QGK/pqTx+K7keFAtLlVNdLRJOg==
|
||||
jsonc-eslint-parser@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-eslint-parser/-/jsonc-eslint-parser-2.3.0.tgz#7c2de97d01bff7227cbef2f25d1025d42a36198b"
|
||||
integrity sha512-9xZPKVYp9DxnM3sd1yAsh/d59iIaswDkai8oTxbursfKYbg/ibjX0IzFt35+VZ8iEW453TVTXztnRvYUQlAfUQ==
|
||||
dependencies:
|
||||
acorn "^7.4.1"
|
||||
eslint-utils "^2.1.0"
|
||||
eslint-visitor-keys "^1.3.0"
|
||||
espree "^6.0.0"
|
||||
semver "^6.3.0"
|
||||
acorn "^8.5.0"
|
||||
eslint-visitor-keys "^3.0.0"
|
||||
espree "^9.0.0"
|
||||
semver "^7.3.5"
|
||||
|
||||
jsonc-parser@^3.2.0:
|
||||
version "3.2.0"
|
||||
@ -1795,7 +1721,7 @@ lodash.merge@^4.6.2:
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
lodash@^4.17.20, lodash@^4.17.21:
|
||||
lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
@ -1888,11 +1814,6 @@ nanoid@^3.3.6:
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
|
||||
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
||||
|
||||
natural-compare-lite@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4"
|
||||
integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==
|
||||
|
||||
natural-compare@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
@ -2211,10 +2132,10 @@ safe-regex-test@^1.0.0:
|
||||
get-intrinsic "^1.1.3"
|
||||
is-regex "^1.1.4"
|
||||
|
||||
sass@^1.64.2:
|
||||
version "1.64.2"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.64.2.tgz#0d9805ad6acf31c59c3acc725fcfb91b7fcc6909"
|
||||
integrity sha512-TnDlfc+CRnUAgLO9D8cQLFu/GIjJIzJCGkE7o4ekIGQOH7T3GetiRR/PsTWJUHhkzcSPrARkPI+gNWn5alCzDg==
|
||||
sass@^1.66.1:
|
||||
version "1.66.1"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.66.1.tgz#04b51c4671e4650aa393740e66a4e58b44d055b1"
|
||||
integrity sha512-50c+zTsZOJVgFfTgwwEzkjA3/QACgdNsKueWPyAR0mRINIvLAStVQBbPg14iuqEQ74NPDbXzJARJ/O4SI1zftA==
|
||||
dependencies:
|
||||
chokidar ">=3.0.0 <4.0.0"
|
||||
immutable "^4.0.0"
|
||||
@ -2225,12 +2146,14 @@ sass@^1.64.2:
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
||||
semver@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
semver@^7.3.5, semver@^7.5.4:
|
||||
version "7.5.4"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
|
||||
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
semver@^7.3.6, semver@^7.3.7:
|
||||
semver@^7.3.6:
|
||||
version "7.3.7"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
|
||||
integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
|
||||
@ -2244,13 +2167,6 @@ semver@^7.3.8:
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
semver@^7.5.4:
|
||||
version "7.5.4"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
|
||||
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
shebang-command@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
||||
@ -2312,7 +2228,7 @@ source-map-support@~0.5.20:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
||||
source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
|
||||
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
@ -2416,10 +2332,10 @@ supports-preserve-symlinks-flag@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||
|
||||
terser@^5.19.2:
|
||||
version "5.19.2"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.19.2.tgz#bdb8017a9a4a8de4663a7983f45c506534f9234e"
|
||||
integrity sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==
|
||||
terser@^5.19.4:
|
||||
version "5.19.4"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.19.4.tgz#941426fa482bf9b40a0308ab2b3cd0cf7c775ebd"
|
||||
integrity sha512-6p1DjHeuluwxDXcuT9VR8p64klWJKo1ILiy19s6C9+0Bh2+NWTX6nD9EPppiER4ICkHDVB1RkVpin/YW2nQn/g==
|
||||
dependencies:
|
||||
"@jridgewell/source-map" "^0.3.3"
|
||||
acorn "^8.8.2"
|
||||
@ -2438,17 +2354,10 @@ to-regex-range@^5.0.1:
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
tslib@^1.8.1:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tsutils@^3.21.0:
|
||||
version "3.21.0"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
|
||||
integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
|
||||
dependencies:
|
||||
tslib "^1.8.1"
|
||||
ts-api-utils@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331"
|
||||
integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==
|
||||
|
||||
type-check@^0.4.0, type-check@~0.4.0:
|
||||
version "0.4.0"
|
||||
@ -2549,19 +2458,6 @@ vite@^4.4.9:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
vue-eslint-parser@^9.1.1:
|
||||
version "9.1.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.1.1.tgz#3f4859be7e9bb7edaa1dc7edb05abffee72bf3dd"
|
||||
integrity sha512-C2aI/r85Q6tYcz4dpgvrs4wH/MqVrRAVIdpYedrxnATDHHkb+TroeRcDpKWGZCx/OcECMWfz7tVwQ8e+Opy6rA==
|
||||
dependencies:
|
||||
debug "^4.3.4"
|
||||
eslint-scope "^7.1.1"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
espree "^9.3.1"
|
||||
esquery "^1.4.0"
|
||||
lodash "^4.17.21"
|
||||
semver "^7.3.6"
|
||||
|
||||
vue-eslint-parser@^9.3.1:
|
||||
version "9.3.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.3.1.tgz#429955e041ae5371df5f9e37ebc29ba046496182"
|
||||
@ -2575,15 +2471,14 @@ vue-eslint-parser@^9.3.1:
|
||||
lodash "^4.17.21"
|
||||
semver "^7.3.6"
|
||||
|
||||
vue-i18n@^9.2.2:
|
||||
version "9.2.2"
|
||||
resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-9.2.2.tgz#aeb49d9424923c77e0d6441e3f21dafcecd0e666"
|
||||
integrity sha512-yswpwtj89rTBhegUAv9Mu37LNznyu3NpyLQmozF3i1hYOhwpG8RjcjIFIIfnu+2MDZJGSZPXaKWvnQA71Yv9TQ==
|
||||
vue-i18n@^9.4.0:
|
||||
version "9.4.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-9.4.0.tgz#13dd07102fd00da3809c5886e250cb505f071ac1"
|
||||
integrity sha512-701V7wv6m/Fesbu58rRJv9Rd3en/9F7Nxyn/NiwcR7bJkEfwflMJg5wVezkeHy1tIqjXME1e1zbHhK1dNaR8mg==
|
||||
dependencies:
|
||||
"@intlify/core-base" "9.2.2"
|
||||
"@intlify/shared" "9.2.2"
|
||||
"@intlify/vue-devtools" "9.2.2"
|
||||
"@vue/devtools-api" "^6.2.1"
|
||||
"@intlify/core-base" "9.4.0"
|
||||
"@intlify/shared" "9.4.0"
|
||||
"@vue/devtools-api" "^6.5.0"
|
||||
|
||||
vue-router@^4.2.4:
|
||||
version "4.2.4"
|
||||
@ -2600,13 +2495,13 @@ vue-template-compiler@^2.7.14:
|
||||
de-indent "^1.0.2"
|
||||
he "^1.2.0"
|
||||
|
||||
vue-tsc@^1.8.8:
|
||||
version "1.8.8"
|
||||
resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-1.8.8.tgz#67317693eb2ef6747e89e6d834eeb6d2deb8871d"
|
||||
integrity sha512-bSydNFQsF7AMvwWsRXD7cBIXaNs/KSjvzWLymq/UtKE36697sboX4EccSHFVxvgdBlI1frYPc/VMKJNB7DFeDQ==
|
||||
vue-tsc@^1.8.11:
|
||||
version "1.8.11"
|
||||
resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-1.8.11.tgz#4a972e58a9eaae72d73e63e0bedacb56391b7cb4"
|
||||
integrity sha512-BzfiMdPqDHBlysx4g26NkfVHSQwGD/lTRausmxN9sFyjXz34OWfsbkh0YsVkX84Hu65In1fFlxHiG39Tr4Vojg==
|
||||
dependencies:
|
||||
"@vue/language-core" "1.8.8"
|
||||
"@vue/typescript" "1.8.8"
|
||||
"@vue/language-core" "1.8.11"
|
||||
"@vue/typescript" "1.8.11"
|
||||
semver "^7.3.8"
|
||||
|
||||
vue@^3.3.4:
|
||||
@ -2675,19 +2570,19 @@ yallist@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yaml-eslint-parser@^0.3.2:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml-eslint-parser/-/yaml-eslint-parser-0.3.2.tgz#c7f5f3904f1c06ad55dc7131a731b018426b4898"
|
||||
integrity sha512-32kYO6kJUuZzqte82t4M/gB6/+11WAuHiEnK7FreMo20xsCKPeFH5tDBU7iWxR7zeJpNnMXfJyXwne48D0hGrg==
|
||||
yaml-eslint-parser@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml-eslint-parser/-/yaml-eslint-parser-1.2.2.tgz#1a9673ebe254328cfc2fa99f297f6d8c9364ccd8"
|
||||
integrity sha512-pEwzfsKbTrB8G3xc/sN7aw1v6A6c/pKxLAkjclnAyo5g5qOh6eL9WGu0o3cSDQZKrTNk4KL4lQSwZW+nBkANEg==
|
||||
dependencies:
|
||||
eslint-visitor-keys "^1.3.0"
|
||||
lodash "^4.17.20"
|
||||
yaml "^1.10.0"
|
||||
eslint-visitor-keys "^3.0.0"
|
||||
lodash "^4.17.21"
|
||||
yaml "^2.0.0"
|
||||
|
||||
yaml@^1.10.0:
|
||||
version "1.10.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||
yaml@^2.0.0:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144"
|
||||
integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==
|
||||
|
||||
yocto-queue@^0.1.0:
|
||||
version "0.1.0"
|
||||
|
||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user