Remove not required F() macro. Frees ~20kb flash.
This commit is contained in:
parent
acf413b616
commit
d6028cbd50
@ -35,7 +35,7 @@ void HoymilesClass::loop()
|
||||
if (_radio->isIdle()) {
|
||||
std::shared_ptr<InverterAbstract> iv = getInverterByPos(inverterPos);
|
||||
if (iv != nullptr) {
|
||||
_messageOutput->print(F("Fetch inverter: "));
|
||||
_messageOutput->print("Fetch inverter: ");
|
||||
_messageOutput->println(iv->serial(), HEX);
|
||||
|
||||
iv->sendStatsRequest(_radio.get());
|
||||
@ -54,19 +54,19 @@ void HoymilesClass::loop()
|
||||
|
||||
// Set limit if required
|
||||
if (iv->SystemConfigPara()->getLastLimitCommandSuccess() == CMD_NOK) {
|
||||
_messageOutput->println(F("Resend ActivePowerControl"));
|
||||
_messageOutput->println("Resend ActivePowerControl");
|
||||
iv->resendActivePowerControlRequest(_radio.get());
|
||||
}
|
||||
|
||||
// Set power status if required
|
||||
if (iv->PowerCommand()->getLastPowerCommandSuccess() == CMD_NOK) {
|
||||
_messageOutput->println(F("Resend PowerCommand"));
|
||||
_messageOutput->println("Resend PowerCommand");
|
||||
iv->resendPowerControlRequest(_radio.get());
|
||||
}
|
||||
|
||||
// Fetch dev info (but first fetch stats)
|
||||
if (iv->Statistics()->getLastUpdate() > 0 && (iv->DevInfo()->getLastUpdateAll() == 0 || iv->DevInfo()->getLastUpdateSimple() == 0)) {
|
||||
_messageOutput->println(F("Request device info"));
|
||||
_messageOutput->println("Request device info");
|
||||
iv->sendDevInfoRequest(_radio.get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,9 +25,9 @@ void HoymilesRadio::init(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pin
|
||||
_radio->setRetries(0, 0);
|
||||
_radio->maskIRQ(true, true, false); // enable only receiving interrupts
|
||||
if (_radio->isChipConnected()) {
|
||||
Hoymiles.getMessageOutput()->println(F("Connection successful"));
|
||||
Hoymiles.getMessageOutput()->println("Connection successful");
|
||||
} else {
|
||||
Hoymiles.getMessageOutput()->println(F("Connection error!!"));
|
||||
Hoymiles.getMessageOutput()->println("Connection error!!");
|
||||
}
|
||||
|
||||
attachInterrupt(digitalPinToInterrupt(pinIRQ), std::bind(&HoymilesRadio::handleIntr, this), FALLING);
|
||||
@ -44,7 +44,7 @@ void HoymilesRadio::loop()
|
||||
}
|
||||
|
||||
if (_packetReceived) {
|
||||
Hoymiles.getMessageOutput()->println(F("Interrupt received"));
|
||||
Hoymiles.getMessageOutput()->println("Interrupt received");
|
||||
while (_radio->available()) {
|
||||
if (!(_rxBuffer.size() > FRAGMENT_BUFFER_SIZE)) {
|
||||
fragment_t f;
|
||||
@ -56,7 +56,7 @@ void HoymilesRadio::loop()
|
||||
_radio->read(f.fragment, f.len);
|
||||
_rxBuffer.push(f);
|
||||
} else {
|
||||
Hoymiles.getMessageOutput()->println(F("Buffer full"));
|
||||
Hoymiles.getMessageOutput()->println("Buffer full");
|
||||
_radio->flush_rx();
|
||||
}
|
||||
}
|
||||
@ -76,11 +76,11 @@ void HoymilesRadio::loop()
|
||||
dumpBuf(buf, f.fragment, f.len);
|
||||
inv->addRxFragment(f.fragment, f.len);
|
||||
} else {
|
||||
Hoymiles.getMessageOutput()->println(F("Inverter Not found!"));
|
||||
Hoymiles.getMessageOutput()->println("Inverter Not found!");
|
||||
}
|
||||
|
||||
} else {
|
||||
Hoymiles.getMessageOutput()->println(F("Frame kaputt"));
|
||||
Hoymiles.getMessageOutput()->println("Frame kaputt");
|
||||
}
|
||||
|
||||
// Remove paket from buffer even it was corrupted
|
||||
@ -89,46 +89,46 @@ void HoymilesRadio::loop()
|
||||
}
|
||||
|
||||
if (_busyFlag && _rxTimeout.occured()) {
|
||||
Hoymiles.getMessageOutput()->println(F("RX Period End"));
|
||||
Hoymiles.getMessageOutput()->println("RX Period End");
|
||||
std::shared_ptr<InverterAbstract> inv = Hoymiles.getInverterBySerial(_commandQueue.front().get()->getTargetAddress());
|
||||
|
||||
if (nullptr != inv) {
|
||||
CommandAbstract* cmd = _commandQueue.front().get();
|
||||
uint8_t verifyResult = inv->verifyAllFragments(cmd);
|
||||
if (verifyResult == FRAGMENT_ALL_MISSING_RESEND) {
|
||||
Hoymiles.getMessageOutput()->println(F("Nothing received, resend whole request"));
|
||||
Hoymiles.getMessageOutput()->println("Nothing received, resend whole request");
|
||||
sendLastPacketAgain();
|
||||
|
||||
} else if (verifyResult == FRAGMENT_ALL_MISSING_TIMEOUT) {
|
||||
Hoymiles.getMessageOutput()->println(F("Nothing received, resend count exeeded"));
|
||||
Hoymiles.getMessageOutput()->println("Nothing received, resend count exeeded");
|
||||
_commandQueue.pop();
|
||||
_busyFlag = false;
|
||||
|
||||
} else if (verifyResult == FRAGMENT_RETRANSMIT_TIMEOUT) {
|
||||
Hoymiles.getMessageOutput()->println(F("Retransmit timeout"));
|
||||
Hoymiles.getMessageOutput()->println("Retransmit timeout");
|
||||
_commandQueue.pop();
|
||||
_busyFlag = false;
|
||||
|
||||
} else if (verifyResult == FRAGMENT_HANDLE_ERROR) {
|
||||
Hoymiles.getMessageOutput()->println(F("Packet handling error"));
|
||||
Hoymiles.getMessageOutput()->println("Packet handling error");
|
||||
_commandQueue.pop();
|
||||
_busyFlag = false;
|
||||
|
||||
} else if (verifyResult > 0) {
|
||||
// Perform Retransmit
|
||||
Hoymiles.getMessageOutput()->print(F("Request retransmit: "));
|
||||
Hoymiles.getMessageOutput()->print("Request retransmit: ");
|
||||
Hoymiles.getMessageOutput()->println(verifyResult);
|
||||
sendRetransmitPacket(verifyResult);
|
||||
|
||||
} else {
|
||||
// Successful received all packages
|
||||
Hoymiles.getMessageOutput()->println(F("Success"));
|
||||
Hoymiles.getMessageOutput()->println("Success");
|
||||
_commandQueue.pop();
|
||||
_busyFlag = false;
|
||||
}
|
||||
} else {
|
||||
// If inverter was not found, assume the command is invalid
|
||||
Hoymiles.getMessageOutput()->println(F("RX: Invalid inverter found"));
|
||||
Hoymiles.getMessageOutput()->println("RX: Invalid inverter found");
|
||||
_commandQueue.pop();
|
||||
_busyFlag = false;
|
||||
}
|
||||
@ -142,7 +142,7 @@ void HoymilesRadio::loop()
|
||||
inv->clearRxFragmentBuffer();
|
||||
sendEsbPacket(cmd);
|
||||
} else {
|
||||
Hoymiles.getMessageOutput()->println(F("TX: Invalid inverter found"));
|
||||
Hoymiles.getMessageOutput()->println("TX: Invalid inverter found");
|
||||
_commandQueue.pop();
|
||||
}
|
||||
}
|
||||
@ -252,11 +252,11 @@ void HoymilesRadio::sendEsbPacket(CommandAbstract* cmd)
|
||||
openWritingPipe(s);
|
||||
_radio->setRetries(3, 15);
|
||||
|
||||
Hoymiles.getMessageOutput()->print(F("TX "));
|
||||
Hoymiles.getMessageOutput()->print("TX ");
|
||||
Hoymiles.getMessageOutput()->print(cmd->getCommandName());
|
||||
Hoymiles.getMessageOutput()->print(F(" Channel: "));
|
||||
Hoymiles.getMessageOutput()->print(" Channel: ");
|
||||
Hoymiles.getMessageOutput()->print(_radio->getChannel());
|
||||
Hoymiles.getMessageOutput()->print(F(" --> "));
|
||||
Hoymiles.getMessageOutput()->print(" --> ");
|
||||
cmd->dumpDataPayload(Hoymiles.getMessageOutput());
|
||||
_radio->write(cmd->getDataPayload(), cmd->getDataSize());
|
||||
|
||||
@ -294,5 +294,5 @@ void HoymilesRadio::dumpBuf(const char* info, uint8_t buf[], uint8_t len)
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
Hoymiles.getMessageOutput()->printf("%02X ", buf[i]);
|
||||
}
|
||||
Hoymiles.getMessageOutput()->println(F(""));
|
||||
Hoymiles.getMessageOutput()->println("");
|
||||
}
|
||||
@ -29,7 +29,7 @@ bool HM_1CH::isValidSerial(uint64_t serial)
|
||||
|
||||
String HM_1CH::typeName()
|
||||
{
|
||||
return F("HM-300, HM-350, HM-400");
|
||||
return "HM-300, HM-350, HM-400";
|
||||
}
|
||||
|
||||
const std::list<byteAssign_t>* HM_1CH::getByteAssignment()
|
||||
|
||||
@ -30,7 +30,7 @@ bool HM_2CH::isValidSerial(uint64_t serial)
|
||||
|
||||
String HM_2CH::typeName()
|
||||
{
|
||||
return F("HM-600, HM-700, HM-800");
|
||||
return "HM-600, HM-700, HM-800";
|
||||
}
|
||||
|
||||
const std::list<byteAssign_t>* HM_2CH::getByteAssignment()
|
||||
|
||||
@ -29,7 +29,7 @@ bool HM_4CH::isValidSerial(uint64_t serial)
|
||||
|
||||
String HM_4CH::typeName()
|
||||
{
|
||||
return F("HM-1000, HM-1200, HM-1500");
|
||||
return "HM-1000, HM-1200, HM-1500";
|
||||
}
|
||||
|
||||
const std::list<byteAssign_t>* HM_4CH::getByteAssignment()
|
||||
|
||||
@ -169,7 +169,7 @@ uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd)
|
||||
{
|
||||
// All missing
|
||||
if (_rxFragmentLastPacketId == 0) {
|
||||
Hoymiles.getMessageOutput()->println(F("All missing"));
|
||||
Hoymiles.getMessageOutput()->println("All missing");
|
||||
if (cmd->getSendCount() <= MAX_RESEND_COUNT) {
|
||||
return FRAGMENT_ALL_MISSING_RESEND;
|
||||
} else {
|
||||
@ -180,7 +180,7 @@ uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd)
|
||||
|
||||
// Last fragment is missing (the one with 0x80)
|
||||
if (_rxFragmentMaxPacketId == 0) {
|
||||
Hoymiles.getMessageOutput()->println(F("Last missing"));
|
||||
Hoymiles.getMessageOutput()->println("Last missing");
|
||||
if (_rxFragmentRetransmitCnt++ < MAX_RETRANSMIT_COUNT) {
|
||||
return _rxFragmentLastPacketId + 1;
|
||||
} else {
|
||||
@ -192,7 +192,7 @@ uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd)
|
||||
// Middle fragment is missing
|
||||
for (uint8_t i = 0; i < _rxFragmentMaxPacketId - 1; i++) {
|
||||
if (!_rxFragmentBuffer[i].wasReceived) {
|
||||
Hoymiles.getMessageOutput()->println(F("Middle missing"));
|
||||
Hoymiles.getMessageOutput()->println("Middle missing");
|
||||
if (_rxFragmentRetransmitCnt++ < MAX_RETRANSMIT_COUNT) {
|
||||
return i + 1;
|
||||
} else {
|
||||
|
||||
@ -64,214 +64,214 @@ void AlarmLogParser::getLogEntry(uint8_t entryId, AlarmLogEntry_t* entry)
|
||||
|
||||
switch (entry->MessageId) {
|
||||
case 1:
|
||||
entry->Message = F("Inverter start");
|
||||
entry->Message = "Inverter start";
|
||||
break;
|
||||
case 2:
|
||||
entry->Message = F("DTU command failed");
|
||||
entry->Message = "DTU command failed";
|
||||
break;
|
||||
case 121:
|
||||
entry->Message = F("Over temperature protection");
|
||||
entry->Message = "Over temperature protection";
|
||||
break;
|
||||
case 124:
|
||||
entry->Message = F("Shut down by remote control");
|
||||
entry->Message = "Shut down by remote control";
|
||||
break;
|
||||
case 125:
|
||||
entry->Message = F("Grid configuration parameter error");
|
||||
entry->Message = "Grid configuration parameter error";
|
||||
break;
|
||||
case 126:
|
||||
entry->Message = F("Software error code 126");
|
||||
entry->Message = "Software error code 126";
|
||||
break;
|
||||
case 127:
|
||||
entry->Message = F("Firmware error");
|
||||
entry->Message = "Firmware error";
|
||||
break;
|
||||
case 128:
|
||||
entry->Message = F("Software error code 128");
|
||||
entry->Message = "Software error code 128";
|
||||
break;
|
||||
case 129:
|
||||
entry->Message = F("Abnormal bias");
|
||||
entry->Message = "Abnormal bias";
|
||||
break;
|
||||
case 130:
|
||||
entry->Message = F("Offline");
|
||||
entry->Message = "Offline";
|
||||
break;
|
||||
case 141:
|
||||
entry->Message = F("Grid: Grid overvoltage");
|
||||
entry->Message = "Grid: Grid overvoltage";
|
||||
break;
|
||||
case 142:
|
||||
entry->Message = F("Grid: 10 min value grid overvoltage");
|
||||
entry->Message = "Grid: 10 min value grid overvoltage";
|
||||
break;
|
||||
case 143:
|
||||
entry->Message = F("Grid: Grid undervoltage");
|
||||
entry->Message = "Grid: Grid undervoltage";
|
||||
break;
|
||||
case 144:
|
||||
entry->Message = F("Grid: Grid overfrequency");
|
||||
entry->Message = "Grid: Grid overfrequency";
|
||||
break;
|
||||
case 145:
|
||||
entry->Message = F("Grid: Grid underfrequency");
|
||||
entry->Message = "Grid: Grid underfrequency";
|
||||
break;
|
||||
case 146:
|
||||
entry->Message = F("Grid: Rapid grid frequency change rate");
|
||||
entry->Message = "Grid: Rapid grid frequency change rate";
|
||||
break;
|
||||
case 147:
|
||||
entry->Message = F("Grid: Power grid outage");
|
||||
entry->Message = "Grid: Power grid outage";
|
||||
break;
|
||||
case 148:
|
||||
entry->Message = F("Grid: Grid disconnection");
|
||||
entry->Message = "Grid: Grid disconnection";
|
||||
break;
|
||||
case 149:
|
||||
entry->Message = F("Grid: Island detected");
|
||||
entry->Message = "Grid: Island detected";
|
||||
break;
|
||||
case 205:
|
||||
entry->Message = F("MPPT-A: Input overvoltage");
|
||||
entry->Message = "MPPT-A: Input overvoltage";
|
||||
break;
|
||||
case 206:
|
||||
entry->Message = F("MPPT-B: Input overvoltage");
|
||||
entry->Message = "MPPT-B: Input overvoltage";
|
||||
break;
|
||||
case 207:
|
||||
entry->Message = F("MPPT-A: Input undervoltage");
|
||||
entry->Message = "MPPT-A: Input undervoltage";
|
||||
break;
|
||||
case 208:
|
||||
entry->Message = F("MPPT-B: Input undervoltage");
|
||||
entry->Message = "MPPT-B: Input undervoltage";
|
||||
break;
|
||||
case 209:
|
||||
entry->Message = F("PV-1: No input");
|
||||
entry->Message = "PV-1: No input";
|
||||
break;
|
||||
case 210:
|
||||
entry->Message = F("PV-2: No input");
|
||||
entry->Message = "PV-2: No input";
|
||||
break;
|
||||
case 211:
|
||||
entry->Message = F("PV-3: No input");
|
||||
entry->Message = "PV-3: No input";
|
||||
break;
|
||||
case 212:
|
||||
entry->Message = F("PV-4: No input");
|
||||
entry->Message = "PV-4: No input";
|
||||
break;
|
||||
case 213:
|
||||
entry->Message = F("MPPT-A: PV-1 & PV-2 abnormal wiring");
|
||||
entry->Message = "MPPT-A: PV-1 & PV-2 abnormal wiring";
|
||||
break;
|
||||
case 214:
|
||||
entry->Message = F("MPPT-B: PV-3 & PV-4 abnormal wiring");
|
||||
entry->Message = "MPPT-B: PV-3 & PV-4 abnormal wiring";
|
||||
break;
|
||||
case 215:
|
||||
entry->Message = F("PV-1: Input overvoltage");
|
||||
entry->Message = "PV-1: Input overvoltage";
|
||||
break;
|
||||
case 216:
|
||||
entry->Message = F("PV-1: Input undervoltage");
|
||||
entry->Message = "PV-1: Input undervoltage";
|
||||
break;
|
||||
case 217:
|
||||
entry->Message = F("PV-2: Input overvoltage");
|
||||
entry->Message = "PV-2: Input overvoltage";
|
||||
break;
|
||||
case 218:
|
||||
entry->Message = F("PV-2: Input undervoltage");
|
||||
entry->Message = "PV-2: Input undervoltage";
|
||||
break;
|
||||
case 219:
|
||||
entry->Message = F("PV-3: Input overvoltage");
|
||||
entry->Message = "PV-3: Input overvoltage";
|
||||
break;
|
||||
case 220:
|
||||
entry->Message = F("PV-3: Input undervoltage");
|
||||
entry->Message = "PV-3: Input undervoltage";
|
||||
break;
|
||||
case 221:
|
||||
entry->Message = F("PV-4: Input overvoltage");
|
||||
entry->Message = "PV-4: Input overvoltage";
|
||||
break;
|
||||
case 222:
|
||||
entry->Message = F("PV-4: Input undervoltage");
|
||||
entry->Message = "PV-4: Input undervoltage";
|
||||
break;
|
||||
case 301:
|
||||
entry->Message = F("Hardware error code 301");
|
||||
entry->Message = "Hardware error code 301";
|
||||
break;
|
||||
case 302:
|
||||
entry->Message = F("Hardware error code 302");
|
||||
entry->Message = "Hardware error code 302";
|
||||
break;
|
||||
case 303:
|
||||
entry->Message = F("Hardware error code 303");
|
||||
entry->Message = "Hardware error code 303";
|
||||
break;
|
||||
case 304:
|
||||
entry->Message = F("Hardware error code 304");
|
||||
entry->Message = "Hardware error code 304";
|
||||
break;
|
||||
case 305:
|
||||
entry->Message = F("Hardware error code 305");
|
||||
entry->Message = "Hardware error code 305";
|
||||
break;
|
||||
case 306:
|
||||
entry->Message = F("Hardware error code 306");
|
||||
entry->Message = "Hardware error code 306";
|
||||
break;
|
||||
case 307:
|
||||
entry->Message = F("Hardware error code 307");
|
||||
entry->Message = "Hardware error code 307";
|
||||
break;
|
||||
case 308:
|
||||
entry->Message = F("Hardware error code 308");
|
||||
entry->Message = "Hardware error code 308";
|
||||
break;
|
||||
case 309:
|
||||
entry->Message = F("Hardware error code 309");
|
||||
entry->Message = "Hardware error code 309";
|
||||
break;
|
||||
case 310:
|
||||
entry->Message = F("Hardware error code 310");
|
||||
entry->Message = "Hardware error code 310";
|
||||
break;
|
||||
case 311:
|
||||
entry->Message = F("Hardware error code 311");
|
||||
entry->Message = "Hardware error code 311";
|
||||
break;
|
||||
case 312:
|
||||
entry->Message = F("Hardware error code 312");
|
||||
entry->Message = "Hardware error code 312";
|
||||
break;
|
||||
case 313:
|
||||
entry->Message = F("Hardware error code 313");
|
||||
entry->Message = "Hardware error code 313";
|
||||
break;
|
||||
case 314:
|
||||
entry->Message = F("Hardware error code 314");
|
||||
entry->Message = "Hardware error code 314";
|
||||
break;
|
||||
case 5041:
|
||||
entry->Message = F("Error code-04 Port 1");
|
||||
entry->Message = "Error code-04 Port 1";
|
||||
break;
|
||||
case 5042:
|
||||
entry->Message = F("Error code-04 Port 2");
|
||||
entry->Message = "Error code-04 Port 2";
|
||||
break;
|
||||
case 5043:
|
||||
entry->Message = F("Error code-04 Port 3");
|
||||
entry->Message = "Error code-04 Port 3";
|
||||
break;
|
||||
case 5044:
|
||||
entry->Message = F("Error code-04 Port 4");
|
||||
entry->Message = "Error code-04 Port 4";
|
||||
break;
|
||||
case 5051:
|
||||
entry->Message = F("PV Input 1 Overvoltage/Undervoltage");
|
||||
entry->Message = "PV Input 1 Overvoltage/Undervoltage";
|
||||
break;
|
||||
case 5052:
|
||||
entry->Message = F("PV Input 2 Overvoltage/Undervoltage");
|
||||
entry->Message = "PV Input 2 Overvoltage/Undervoltage";
|
||||
break;
|
||||
case 5053:
|
||||
entry->Message = F("PV Input 3 Overvoltage/Undervoltage");
|
||||
entry->Message = "PV Input 3 Overvoltage/Undervoltage";
|
||||
break;
|
||||
case 5054:
|
||||
entry->Message = F("PV Input 4 Overvoltage/Undervoltage");
|
||||
entry->Message = "PV Input 4 Overvoltage/Undervoltage";
|
||||
break;
|
||||
case 5060:
|
||||
entry->Message = F("Abnormal bias");
|
||||
entry->Message = "Abnormal bias";
|
||||
break;
|
||||
case 5070:
|
||||
entry->Message = F("Over temperature protection");
|
||||
entry->Message = "Over temperature protection";
|
||||
break;
|
||||
case 5080:
|
||||
entry->Message = F("Grid Overvoltage/Undervoltage");
|
||||
entry->Message = "Grid Overvoltage/Undervoltage";
|
||||
break;
|
||||
case 5090:
|
||||
entry->Message = F("Grid Overfrequency/Underfrequency");
|
||||
entry->Message = "Grid Overfrequency/Underfrequency";
|
||||
break;
|
||||
case 5100:
|
||||
entry->Message = F("Island detected");
|
||||
entry->Message = "Island detected";
|
||||
break;
|
||||
case 5120:
|
||||
entry->Message = F("EEPROM reading and writing error");
|
||||
entry->Message = "EEPROM reading and writing error";
|
||||
break;
|
||||
case 5150:
|
||||
entry->Message = F("10 min value grid overvoltage");
|
||||
entry->Message = "10 min value grid overvoltage";
|
||||
break;
|
||||
case 5200:
|
||||
entry->Message = F("Firmware error");
|
||||
entry->Message = "Firmware error";
|
||||
break;
|
||||
case 8310:
|
||||
entry->Message = F("Shut down");
|
||||
entry->Message = "Shut down";
|
||||
break;
|
||||
case 9000:
|
||||
entry->Message = F("Microinverter is suspected of being stolen");
|
||||
entry->Message = "Microinverter is suspected of being stolen";
|
||||
break;
|
||||
default:
|
||||
entry->Message = F("Unknown");
|
||||
entry->Message = "Unknown";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,58 +29,58 @@ String ResetReasonClass::get_reset_reason_verbose(uint8_t cpu_id)
|
||||
|
||||
switch (reason) {
|
||||
case 1:
|
||||
reason_str = F("Vbat power on reset");
|
||||
reason_str = "Vbat power on reset";
|
||||
break;
|
||||
case 3:
|
||||
reason_str = F("Software reset digital core");
|
||||
reason_str = "Software reset digital core";
|
||||
break;
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
case 4:
|
||||
reason_str = F("Legacy watch dog reset digital core");
|
||||
reason_str = "Legacy watch dog reset digital core";
|
||||
break;
|
||||
#endif
|
||||
case 5:
|
||||
reason_str = F("Deep Sleep reset digital core");
|
||||
reason_str = "Deep Sleep reset digital core";
|
||||
break;
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
case 6:
|
||||
reason_str = F("Reset by SLC module, reset digital core");
|
||||
reason_str = "Reset by SLC module, reset digital core";
|
||||
break;
|
||||
#endif
|
||||
case 7:
|
||||
reason_str = F("Timer Group0 Watch dog reset digital core");
|
||||
reason_str = "Timer Group0 Watch dog reset digital core";
|
||||
break;
|
||||
case 8:
|
||||
reason_str = F("Timer Group1 Watch dog reset digital core");
|
||||
reason_str = "Timer Group1 Watch dog reset digital core";
|
||||
break;
|
||||
case 9:
|
||||
reason_str = F("RTC Watch dog Reset digital core");
|
||||
reason_str = "RTC Watch dog Reset digital core";
|
||||
break;
|
||||
case 10:
|
||||
reason_str = F("Instrusion tested to reset CPU");
|
||||
reason_str = "Instrusion tested to reset CPU";
|
||||
break;
|
||||
case 11:
|
||||
reason_str = F("Time Group reset CPU");
|
||||
reason_str = "Time Group reset CPU";
|
||||
break;
|
||||
case 12:
|
||||
reason_str = F("Software reset CPU");
|
||||
reason_str = "Software reset CPU";
|
||||
break;
|
||||
case 13:
|
||||
reason_str = F("RTC Watch dog Reset CPU");
|
||||
reason_str = "RTC Watch dog Reset CPU";
|
||||
break;
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
case 14:
|
||||
reason_str = F("for APP CPU, reset by PRO CPU");
|
||||
reason_str = "for APP CPU, reset by PRO CPU";
|
||||
break;
|
||||
#endif
|
||||
case 15:
|
||||
reason_str = F("Reset when the vdd voltage is not stable");
|
||||
reason_str = "Reset when the vdd voltage is not stable";
|
||||
break;
|
||||
case 16:
|
||||
reason_str = F("RTC Watch dog reset digital core and rtc module");
|
||||
reason_str = "RTC Watch dog reset digital core and rtc module";
|
||||
break;
|
||||
default:
|
||||
reason_str = F("NO_MEAN");
|
||||
reason_str = "NO_MEAN";
|
||||
}
|
||||
|
||||
return reason_str;
|
||||
@ -95,58 +95,58 @@ String ResetReasonClass::get_reset_reason_short(uint8_t cpu_id)
|
||||
|
||||
switch (reason) {
|
||||
case 1:
|
||||
reason_str = F("POWERON_RESET");
|
||||
reason_str = "POWERON_RESET";
|
||||
break;
|
||||
case 3:
|
||||
reason_str = F("SW_RESET");
|
||||
reason_str = "SW_RESET";
|
||||
break;
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
case 4:
|
||||
reason_str = F("OWDT_RESET");
|
||||
reason_str = "OWDT_RESET";
|
||||
break;
|
||||
#endif
|
||||
case 5:
|
||||
reason_str = F("DEEPSLEEP_RESET");
|
||||
reason_str = "DEEPSLEEP_RESET";
|
||||
break;
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
case 6:
|
||||
reason_str = F("SDIO_RESET");
|
||||
reason_str = "SDIO_RESET";
|
||||
break;
|
||||
#endif
|
||||
case 7:
|
||||
reason_str = F("TG0WDT_SYS_RESET");
|
||||
reason_str = "TG0WDT_SYS_RESET";
|
||||
break;
|
||||
case 8:
|
||||
reason_str = F("TG1WDT_SYS_RESET");
|
||||
reason_str = "TG1WDT_SYS_RESET";
|
||||
break;
|
||||
case 9:
|
||||
reason_str = F("RTCWDT_SYS_RESET");
|
||||
reason_str = "RTCWDT_SYS_RESET";
|
||||
break;
|
||||
case 10:
|
||||
reason_str = F("INTRUSION_RESET");
|
||||
reason_str = "INTRUSION_RESET";
|
||||
break;
|
||||
case 11:
|
||||
reason_str = F("TGWDT_CPU_RESET");
|
||||
reason_str = "TGWDT_CPU_RESET";
|
||||
break;
|
||||
case 12:
|
||||
reason_str = F("SW_CPU_RESET");
|
||||
reason_str = "SW_CPU_RESET";
|
||||
break;
|
||||
case 13:
|
||||
reason_str = F("RTCWDT_CPU_RESET");
|
||||
reason_str = "RTCWDT_CPU_RESET";
|
||||
break;
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
case 14:
|
||||
reason_str = F("EXT_CPU_RESET");
|
||||
reason_str = "EXT_CPU_RESET";
|
||||
break;
|
||||
#endif
|
||||
case 15:
|
||||
reason_str = F("RTCWDT_BROWN_OUT_RESET");
|
||||
reason_str = "RTCWDT_BROWN_OUT_RESET";
|
||||
break;
|
||||
case 16:
|
||||
reason_str = F("RTCWDT_RTC_RESET");
|
||||
reason_str = "RTCWDT_RTC_RESET";
|
||||
break;
|
||||
default:
|
||||
reason_str = F("NO_MEAN");
|
||||
reason_str = "NO_MEAN";
|
||||
}
|
||||
|
||||
return reason_str;
|
||||
|
||||
@ -128,7 +128,7 @@ bool ConfigurationClass::read()
|
||||
// Deserialize the JSON document
|
||||
DeserializationError error = deserializeJson(doc, f);
|
||||
if (error) {
|
||||
MessageOutput.println(F("Failed to read file, using default configuration"));
|
||||
MessageOutput.println("Failed to read file, using default configuration");
|
||||
}
|
||||
|
||||
JsonObject cfg = doc["cfg"];
|
||||
@ -255,7 +255,7 @@ void ConfigurationClass::migrate()
|
||||
{
|
||||
File f = LittleFS.open(CONFIG_FILENAME, "r", false);
|
||||
if (!f) {
|
||||
MessageOutput.println(F("Failed to open file, cancel migration"));
|
||||
MessageOutput.println("Failed to open file, cancel migration");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -21,27 +21,27 @@ void InverterSettingsClass::init()
|
||||
const PinMapping_t& pin = PinMapping.get();
|
||||
|
||||
// Initialize inverter communication
|
||||
MessageOutput.print(F("Initialize Hoymiles interface... "));
|
||||
MessageOutput.print("Initialize Hoymiles interface... ");
|
||||
if (PinMapping.isValidNrf24Config()) {
|
||||
SPIClass* spiClass = new SPIClass(VSPI);
|
||||
spiClass->begin(pin.nrf24_clk, pin.nrf24_miso, pin.nrf24_mosi, pin.nrf24_cs);
|
||||
Hoymiles.setMessageOutput(&MessageOutput);
|
||||
Hoymiles.init(spiClass, pin.nrf24_en, pin.nrf24_irq);
|
||||
|
||||
MessageOutput.println(F(" Setting radio PA level... "));
|
||||
MessageOutput.println(" Setting radio PA level... ");
|
||||
Hoymiles.getRadio()->setPALevel((rf24_pa_dbm_e)config.Dtu_PaLevel);
|
||||
|
||||
MessageOutput.println(F(" Setting DTU serial... "));
|
||||
MessageOutput.println(" Setting DTU serial... ");
|
||||
Hoymiles.getRadio()->setDtuSerial(config.Dtu_Serial);
|
||||
|
||||
MessageOutput.println(F(" Setting poll interval... "));
|
||||
MessageOutput.println(" Setting poll interval... ");
|
||||
Hoymiles.setPollInterval(config.Dtu_PollInterval);
|
||||
|
||||
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
|
||||
if (config.Inverter[i].Serial > 0) {
|
||||
MessageOutput.print(F(" Adding inverter: "));
|
||||
MessageOutput.print(" Adding inverter: ");
|
||||
MessageOutput.print(config.Inverter[i].Serial, HEX);
|
||||
MessageOutput.print(F(" - "));
|
||||
MessageOutput.print(" - ");
|
||||
MessageOutput.print(config.Inverter[i].Name);
|
||||
auto inv = Hoymiles.addInverter(
|
||||
config.Inverter[i].Name,
|
||||
@ -53,12 +53,12 @@ void InverterSettingsClass::init()
|
||||
inv->Statistics()->setChannelFieldOffset(TYPE_DC, static_cast<ChannelNum_t>(c), FLD_YT, config.Inverter[i].channel[c].YieldTotalOffset);
|
||||
}
|
||||
}
|
||||
MessageOutput.println(F(" done"));
|
||||
MessageOutput.println(" done");
|
||||
}
|
||||
}
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
} else {
|
||||
MessageOutput.println(F("Invalid pin config"));
|
||||
MessageOutput.println("Invalid pin config");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -121,26 +121,26 @@ void MqttHandleHassClass::publishField(std::shared_ptr<InverterAbstract> inv, Ch
|
||||
}
|
||||
|
||||
DynamicJsonDocument root(1024);
|
||||
root[F("name")] = name;
|
||||
root[F("stat_t")] = stateTopic;
|
||||
root[F("uniq_id")] = serial + "_ch" + chanNum + "_" + fieldName;
|
||||
root["name"] = name;
|
||||
root["stat_t"] = stateTopic;
|
||||
root["uniq_id"] = serial + "_ch" + chanNum + "_" + fieldName;
|
||||
|
||||
String unit_of_measure = inv->Statistics()->getChannelFieldUnit(type, channel, fieldType.fieldId);
|
||||
if (unit_of_measure != "") {
|
||||
root[F("unit_of_meas")] = unit_of_measure;
|
||||
root["unit_of_meas"] = unit_of_measure;
|
||||
}
|
||||
|
||||
JsonObject deviceObj = root.createNestedObject("dev");
|
||||
createDeviceInfo(deviceObj, inv);
|
||||
|
||||
if (Configuration.get().Mqtt_Hass_Expire) {
|
||||
root[F("exp_aft")] = Hoymiles.getNumInverters() * Configuration.get().Mqtt_PublishInterval * 3;
|
||||
root["exp_aft"] = Hoymiles.getNumInverters() * Configuration.get().Mqtt_PublishInterval * 3;
|
||||
}
|
||||
if (devCls != 0) {
|
||||
root[F("dev_cla")] = devCls;
|
||||
root["dev_cla"] = devCls;
|
||||
}
|
||||
if (stateCls != 0) {
|
||||
root[F("stat_cla")] = stateCls;
|
||||
root["stat_cla"] = stateCls;
|
||||
}
|
||||
|
||||
char buffer[512];
|
||||
@ -166,17 +166,17 @@ void MqttHandleHassClass::publishInverterButton(std::shared_ptr<InverterAbstract
|
||||
String cmdTopic = MqttSettings.getPrefix() + serial + "/" + subTopic;
|
||||
|
||||
DynamicJsonDocument root(1024);
|
||||
root[F("name")] = String(inv->name()) + " " + caption;
|
||||
root[F("uniq_id")] = serial + "_" + buttonId;
|
||||
root["name"] = String(inv->name()) + " " + caption;
|
||||
root["uniq_id"] = serial + "_" + buttonId;
|
||||
if (strcmp(icon, "")) {
|
||||
root[F("ic")] = icon;
|
||||
root["ic"] = icon;
|
||||
}
|
||||
if (strcmp(deviceClass, "")) {
|
||||
root[F("dev_cla")] = deviceClass;
|
||||
root["dev_cla"] = deviceClass;
|
||||
}
|
||||
root[F("ent_cat")] = category;
|
||||
root[F("cmd_t")] = cmdTopic;
|
||||
root[F("payload_press")] = payload;
|
||||
root["ent_cat"] = category;
|
||||
root["cmd_t"] = cmdTopic;
|
||||
root["payload_press"] = payload;
|
||||
|
||||
JsonObject deviceObj = root.createNestedObject("dev");
|
||||
createDeviceInfo(deviceObj, inv);
|
||||
@ -205,17 +205,17 @@ void MqttHandleHassClass::publishInverterNumber(
|
||||
String statTopic = MqttSettings.getPrefix() + serial + "/" + stateTopic;
|
||||
|
||||
DynamicJsonDocument root(1024);
|
||||
root[F("name")] = String(inv->name()) + " " + caption;
|
||||
root[F("uniq_id")] = serial + "_" + buttonId;
|
||||
root["name"] = String(inv->name()) + " " + caption;
|
||||
root["uniq_id"] = serial + "_" + buttonId;
|
||||
if (strcmp(icon, "")) {
|
||||
root[F("ic")] = icon;
|
||||
root["ic"] = icon;
|
||||
}
|
||||
root[F("ent_cat")] = category;
|
||||
root[F("cmd_t")] = cmdTopic;
|
||||
root[F("stat_t")] = statTopic;
|
||||
root[F("unit_of_meas")] = unitOfMeasure;
|
||||
root[F("min")] = min;
|
||||
root[F("max")] = max;
|
||||
root["ent_cat"] = category;
|
||||
root["cmd_t"] = cmdTopic;
|
||||
root["stat_t"] = statTopic;
|
||||
root["unit_of_meas"] = unitOfMeasure;
|
||||
root["min"] = min;
|
||||
root["max"] = max;
|
||||
|
||||
JsonObject deviceObj = root.createNestedObject("dev");
|
||||
createDeviceInfo(deviceObj, inv);
|
||||
@ -240,11 +240,11 @@ void MqttHandleHassClass::publishInverterBinarySensor(std::shared_ptr<InverterAb
|
||||
String statTopic = MqttSettings.getPrefix() + serial + "/" + subTopic;
|
||||
|
||||
DynamicJsonDocument root(1024);
|
||||
root[F("name")] = String(inv->name()) + " " + caption;
|
||||
root[F("uniq_id")] = serial + "_" + sensorId;
|
||||
root[F("stat_t")] = statTopic;
|
||||
root[F("pl_on")] = payload_on;
|
||||
root[F("pl_off")] = payload_off;
|
||||
root["name"] = String(inv->name()) + " " + caption;
|
||||
root["uniq_id"] = serial + "_" + sensorId;
|
||||
root["stat_t"] = statTopic;
|
||||
root["pl_on"] = payload_on;
|
||||
root["pl_off"] = payload_off;
|
||||
|
||||
JsonObject deviceObj = root.createNestedObject("dev");
|
||||
createDeviceInfo(deviceObj, inv);
|
||||
@ -256,12 +256,12 @@ void MqttHandleHassClass::publishInverterBinarySensor(std::shared_ptr<InverterAb
|
||||
|
||||
void MqttHandleHassClass::createDeviceInfo(JsonObject& object, std::shared_ptr<InverterAbstract> inv)
|
||||
{
|
||||
object[F("name")] = inv->name();
|
||||
object[F("ids")] = inv->serialString();
|
||||
object[F("cu")] = String(F("http://")) + NetworkSettings.localIP().toString();
|
||||
object[F("mf")] = F("OpenDTU");
|
||||
object[F("mdl")] = inv->typeName();
|
||||
object[F("sw")] = AUTO_GIT_HASH;
|
||||
object["name"] = inv->name();
|
||||
object["ids"] = inv->serialString();
|
||||
object["cu"] = String("http://") + NetworkSettings.localIP().toString();
|
||||
object["mf"] = "OpenDTU";
|
||||
object["mdl"] = inv->typeName();
|
||||
object["sw"] = AUTO_GIT_HASH;
|
||||
}
|
||||
|
||||
void MqttHandleHassClass::publish(const String& subtopic, const String& payload)
|
||||
|
||||
@ -185,7 +185,7 @@ void MqttHandleInverterClass::onMqttMessage(const espMqttClientTypes::MessagePro
|
||||
auto inv = Hoymiles.getInverterBySerial(serial);
|
||||
|
||||
if (inv == nullptr) {
|
||||
MessageOutput.println(F("Inverter not found"));
|
||||
MessageOutput.println("Inverter not found");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -14,11 +14,11 @@ void MqttSettingsClass::NetworkEvent(network_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case network_event::NETWORK_GOT_IP:
|
||||
MessageOutput.println(F("Network connected"));
|
||||
MessageOutput.println("Network connected");
|
||||
performConnect();
|
||||
break;
|
||||
case network_event::NETWORK_DISCONNECTED:
|
||||
MessageOutput.println(F("Network lost connection"));
|
||||
MessageOutput.println("Network lost connection");
|
||||
mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
|
||||
break;
|
||||
default:
|
||||
@ -28,7 +28,7 @@ void MqttSettingsClass::NetworkEvent(network_event event)
|
||||
|
||||
void MqttSettingsClass::onMqttConnect(bool sessionPresent)
|
||||
{
|
||||
MessageOutput.println(F("Connected to MQTT."));
|
||||
MessageOutput.println("Connected to MQTT.");
|
||||
const CONFIG_T& config = Configuration.get();
|
||||
publish(config.Mqtt_LwtTopic, config.Mqtt_LwtValue_Online);
|
||||
|
||||
@ -51,30 +51,30 @@ void MqttSettingsClass::unsubscribe(const String& topic)
|
||||
|
||||
void MqttSettingsClass::onMqttDisconnect(espMqttClientTypes::DisconnectReason reason)
|
||||
{
|
||||
MessageOutput.println(F("Disconnected from MQTT."));
|
||||
MessageOutput.println("Disconnected from MQTT.");
|
||||
|
||||
MessageOutput.print(F("Disconnect reason:"));
|
||||
MessageOutput.print("Disconnect reason:");
|
||||
switch (reason) {
|
||||
case espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED:
|
||||
MessageOutput.println(F("TCP_DISCONNECTED"));
|
||||
MessageOutput.println("TCP_DISCONNECTED");
|
||||
break;
|
||||
case espMqttClientTypes::DisconnectReason::MQTT_UNACCEPTABLE_PROTOCOL_VERSION:
|
||||
MessageOutput.println(F("MQTT_UNACCEPTABLE_PROTOCOL_VERSION"));
|
||||
MessageOutput.println("MQTT_UNACCEPTABLE_PROTOCOL_VERSION");
|
||||
break;
|
||||
case espMqttClientTypes::DisconnectReason::MQTT_IDENTIFIER_REJECTED:
|
||||
MessageOutput.println(F("MQTT_IDENTIFIER_REJECTED"));
|
||||
MessageOutput.println("MQTT_IDENTIFIER_REJECTED");
|
||||
break;
|
||||
case espMqttClientTypes::DisconnectReason::MQTT_SERVER_UNAVAILABLE:
|
||||
MessageOutput.println(F("MQTT_SERVER_UNAVAILABLE"));
|
||||
MessageOutput.println("MQTT_SERVER_UNAVAILABLE");
|
||||
break;
|
||||
case espMqttClientTypes::DisconnectReason::MQTT_MALFORMED_CREDENTIALS:
|
||||
MessageOutput.println(F("MQTT_MALFORMED_CREDENTIALS"));
|
||||
MessageOutput.println("MQTT_MALFORMED_CREDENTIALS");
|
||||
break;
|
||||
case espMqttClientTypes::DisconnectReason::MQTT_NOT_AUTHORIZED:
|
||||
MessageOutput.println(F("MQTT_NOT_AUTHORIZED"));
|
||||
MessageOutput.println("MQTT_NOT_AUTHORIZED");
|
||||
break;
|
||||
default:
|
||||
MessageOutput.println(F("Unknown"));
|
||||
MessageOutput.println("Unknown");
|
||||
}
|
||||
mqttReconnectTimer.once(
|
||||
2, +[](MqttSettingsClass* instance) { instance->performConnect(); }, this);
|
||||
@ -82,7 +82,7 @@ void MqttSettingsClass::onMqttDisconnect(espMqttClientTypes::DisconnectReason re
|
||||
|
||||
void MqttSettingsClass::onMqttMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
|
||||
{
|
||||
MessageOutput.print(F("Received MQTT message on topic: "));
|
||||
MessageOutput.print("Received MQTT message on topic: ");
|
||||
MessageOutput.println(topic);
|
||||
|
||||
_mqttSubscribeParser.handle_message(properties, topic, payload, len, index, total);
|
||||
@ -97,7 +97,7 @@ void MqttSettingsClass::performConnect()
|
||||
using std::placeholders::_4;
|
||||
using std::placeholders::_5;
|
||||
using std::placeholders::_6;
|
||||
MessageOutput.println(F("Connecting to MQTT..."));
|
||||
MessageOutput.println("Connecting to MQTT...");
|
||||
const CONFIG_T& config = Configuration.get();
|
||||
willTopic = getPrefix() + config.Mqtt_LwtTopic;
|
||||
clientId = NetworkSettings.getApName();
|
||||
|
||||
@ -29,19 +29,19 @@ void NetworkSettingsClass::NetworkEvent(WiFiEvent_t event)
|
||||
{
|
||||
switch (event) {
|
||||
case ARDUINO_EVENT_ETH_START:
|
||||
MessageOutput.println(F("ETH start"));
|
||||
MessageOutput.println("ETH start");
|
||||
if (_networkMode == network_mode::Ethernet) {
|
||||
raiseEvent(network_event::NETWORK_START);
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_STOP:
|
||||
MessageOutput.println(F("ETH stop"));
|
||||
MessageOutput.println("ETH stop");
|
||||
if (_networkMode == network_mode::Ethernet) {
|
||||
raiseEvent(network_event::NETWORK_STOP);
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||
MessageOutput.println(F("ETH connected"));
|
||||
MessageOutput.println("ETH connected");
|
||||
_ethConnected = true;
|
||||
raiseEvent(network_event::NETWORK_CONNECTED);
|
||||
break;
|
||||
@ -52,22 +52,22 @@ void NetworkSettingsClass::NetworkEvent(WiFiEvent_t event)
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||
MessageOutput.println(F("ETH disconnected"));
|
||||
MessageOutput.println("ETH disconnected");
|
||||
_ethConnected = false;
|
||||
if (_networkMode == network_mode::Ethernet) {
|
||||
raiseEvent(network_event::NETWORK_DISCONNECTED);
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
||||
MessageOutput.println(F("WiFi connected"));
|
||||
MessageOutput.println("WiFi connected");
|
||||
if (_networkMode == network_mode::WiFi) {
|
||||
raiseEvent(network_event::NETWORK_CONNECTED);
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||
MessageOutput.println(F("WiFi disconnected"));
|
||||
MessageOutput.println("WiFi disconnected");
|
||||
if (_networkMode == network_mode::WiFi) {
|
||||
MessageOutput.println(F("Try reconnecting"));
|
||||
MessageOutput.println("Try reconnecting");
|
||||
WiFi.reconnect();
|
||||
raiseEvent(network_event::NETWORK_DISCONNECTED);
|
||||
}
|
||||
@ -152,7 +152,7 @@ void NetworkSettingsClass::loop()
|
||||
if (_ethConnected) {
|
||||
if (_networkMode != network_mode::Ethernet) {
|
||||
// Do stuff when switching to Ethernet mode
|
||||
MessageOutput.println(F("Switch to Ethernet mode"));
|
||||
MessageOutput.println("Switch to Ethernet mode");
|
||||
_networkMode = network_mode::Ethernet;
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
setStaticIp();
|
||||
@ -161,7 +161,7 @@ void NetworkSettingsClass::loop()
|
||||
} else
|
||||
if (_networkMode != network_mode::WiFi) {
|
||||
// Do stuff when switching to Ethernet mode
|
||||
MessageOutput.println(F("Switch to WiFi mode"));
|
||||
MessageOutput.println("Switch to WiFi mode");
|
||||
_networkMode = network_mode::WiFi;
|
||||
enableAdminMode();
|
||||
applyConfig();
|
||||
@ -182,7 +182,7 @@ void NetworkSettingsClass::loop()
|
||||
// seconds, disable the internal Access Point
|
||||
if (adminTimeoutCounter > ADMIN_TIMEOUT) {
|
||||
adminEnabled = false;
|
||||
MessageOutput.println(F("Admin mode disabled"));
|
||||
MessageOutput.println("Admin mode disabled");
|
||||
setupMode();
|
||||
}
|
||||
// It's nearly not possible to use the internal AP if the
|
||||
@ -193,16 +193,16 @@ void NetworkSettingsClass::loop()
|
||||
connectRedoTimer = 0;
|
||||
} else {
|
||||
if (connectTimeoutTimer > WIFI_RECONNECT_TIMEOUT && !forceDisconnection) {
|
||||
MessageOutput.print(F("Disable search for AP... "));
|
||||
MessageOutput.print("Disable search for AP... ");
|
||||
WiFi.mode(WIFI_AP);
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
connectRedoTimer = 0;
|
||||
forceDisconnection = true;
|
||||
}
|
||||
if (connectRedoTimer > WIFI_RECONNECT_REDO_TIMEOUT && forceDisconnection) {
|
||||
MessageOutput.print(F("Enable search for AP... "));
|
||||
MessageOutput.print("Enable search for AP... ");
|
||||
WiFi.mode(WIFI_AP_STA);
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
applyConfig();
|
||||
connectTimeoutTimer = 0;
|
||||
forceDisconnection = false;
|
||||
@ -220,28 +220,28 @@ void NetworkSettingsClass::applyConfig()
|
||||
if (!strcmp(Configuration.get().WiFi_Ssid, "")) {
|
||||
return;
|
||||
}
|
||||
MessageOutput.print(F("Configuring WiFi STA using "));
|
||||
MessageOutput.print("Configuring WiFi STA using ");
|
||||
if (strcmp(WiFi.SSID().c_str(), Configuration.get().WiFi_Ssid) || strcmp(WiFi.psk().c_str(), Configuration.get().WiFi_Password)) {
|
||||
MessageOutput.print(F("new credentials... "));
|
||||
MessageOutput.print("new credentials... ");
|
||||
WiFi.begin(
|
||||
Configuration.get().WiFi_Ssid,
|
||||
Configuration.get().WiFi_Password);
|
||||
} else {
|
||||
MessageOutput.print(F("existing credentials... "));
|
||||
MessageOutput.print("existing credentials... ");
|
||||
WiFi.begin();
|
||||
}
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
setStaticIp();
|
||||
}
|
||||
|
||||
void NetworkSettingsClass::setHostname()
|
||||
{
|
||||
MessageOutput.print(F("Setting Hostname... "));
|
||||
MessageOutput.print("Setting Hostname... ");
|
||||
if (_networkMode == network_mode::WiFi) {
|
||||
if (WiFi.hostname(getHostname())) {
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
} else {
|
||||
MessageOutput.println(F("failed"));
|
||||
MessageOutput.println("failed");
|
||||
}
|
||||
|
||||
// Evil bad hack to get the hostname set up correctly
|
||||
@ -251,9 +251,9 @@ void NetworkSettingsClass::setHostname()
|
||||
}
|
||||
else if (_networkMode == network_mode::Ethernet) {
|
||||
if (ETH.setHostname(getHostname().c_str())) {
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
} else {
|
||||
MessageOutput.println(F("failed"));
|
||||
MessageOutput.println("failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -262,34 +262,34 @@ void NetworkSettingsClass::setStaticIp()
|
||||
{
|
||||
if (_networkMode == network_mode::WiFi) {
|
||||
if (Configuration.get().WiFi_Dhcp) {
|
||||
MessageOutput.print(F("Configuring WiFi STA DHCP IP... "));
|
||||
MessageOutput.print("Configuring WiFi STA DHCP IP... ");
|
||||
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
} else {
|
||||
MessageOutput.print(F("Configuring WiFi STA static IP... "));
|
||||
MessageOutput.print("Configuring WiFi STA static IP... ");
|
||||
WiFi.config(
|
||||
IPAddress(Configuration.get().WiFi_Ip),
|
||||
IPAddress(Configuration.get().WiFi_Gateway),
|
||||
IPAddress(Configuration.get().WiFi_Netmask),
|
||||
IPAddress(Configuration.get().WiFi_Dns1),
|
||||
IPAddress(Configuration.get().WiFi_Dns2));
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
}
|
||||
}
|
||||
else if (_networkMode == network_mode::Ethernet) {
|
||||
if (Configuration.get().WiFi_Dhcp) {
|
||||
MessageOutput.print(F("Configuring Ethernet DHCP IP... "));
|
||||
MessageOutput.print("Configuring Ethernet DHCP IP... ");
|
||||
ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
} else {
|
||||
MessageOutput.print(F("Configuring Ethernet static IP... "));
|
||||
MessageOutput.print("Configuring Ethernet static IP... ");
|
||||
ETH.config(
|
||||
IPAddress(Configuration.get().WiFi_Ip),
|
||||
IPAddress(Configuration.get().WiFi_Gateway),
|
||||
IPAddress(Configuration.get().WiFi_Netmask),
|
||||
IPAddress(Configuration.get().WiFi_Dns1),
|
||||
IPAddress(Configuration.get().WiFi_Dns2));
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ bool PinMappingClass::init(const String& deviceMapping)
|
||||
// Deserialize the JSON document
|
||||
DeserializationError error = deserializeJson(doc, f);
|
||||
if (error) {
|
||||
MessageOutput.println(F("Failed to read file, using default configuration"));
|
||||
MessageOutput.println("Failed to read file, using default configuration");
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < doc.size(); i++) {
|
||||
|
||||
@ -73,7 +73,7 @@ bool WebApiClass::checkCredentials(AsyncWebServerRequest* request)
|
||||
|
||||
// WebAPI should set the X-Requested-With to prevent browser internal auth dialogs
|
||||
if (!request->hasHeader("X-Requested-With")) {
|
||||
r->addHeader(F("WWW-Authenticate"), F("Basic realm=\"Login Required\""));
|
||||
r->addHeader("WWW-Authenticate", "Basic realm=\"Login Required\"");
|
||||
}
|
||||
request->send(r);
|
||||
|
||||
|
||||
@ -59,11 +59,11 @@ void WebApiConfigClass::onConfigDelete(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -72,8 +72,8 @@ void WebApiConfigClass::onConfigDelete(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -83,32 +83,32 @@ void WebApiConfigClass::onConfigDelete(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(root.containsKey("delete"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("delete")].as<bool>() == false) {
|
||||
retMsg[F("message")] = F("Not deleted anything!");
|
||||
retMsg[F("code")] = WebApiError::ConfigNotDeleted;
|
||||
if (root["delete"].as<bool>() == false) {
|
||||
retMsg["message"] = "Not deleted anything!";
|
||||
retMsg["code"] = WebApiError::ConfigNotDeleted;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Configuration resettet. Rebooting now...");
|
||||
retMsg[F("code")] = WebApiError::ConfigSuccess;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Configuration resettet. Rebooting now...";
|
||||
retMsg["code"] = WebApiError::ConfigSuccess;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -125,7 +125,7 @@ void WebApiConfigClass::onConfigListGet(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
JsonArray data = root.createNestedArray(F("configs"));
|
||||
JsonArray data = root.createNestedArray("configs");
|
||||
|
||||
File rootfs = LittleFS.open("/");
|
||||
File file = rootfs.openNextFile();
|
||||
|
||||
@ -37,37 +37,37 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
|
||||
const PinMapping_t& pin = PinMapping.get();
|
||||
|
||||
JsonObject curPin = root.createNestedObject("curPin");
|
||||
curPin[F("name")] = config.Dev_PinMapping;
|
||||
curPin["name"] = config.Dev_PinMapping;
|
||||
|
||||
JsonObject nrfPinObj = curPin.createNestedObject("nrf24");
|
||||
nrfPinObj[F("clk")] = pin.nrf24_clk;
|
||||
nrfPinObj[F("cs")] = pin.nrf24_cs;
|
||||
nrfPinObj[F("en")] = pin.nrf24_en;
|
||||
nrfPinObj[F("irq")] = pin.nrf24_irq;
|
||||
nrfPinObj[F("miso")] = pin.nrf24_miso;
|
||||
nrfPinObj[F("mosi")] = pin.nrf24_mosi;
|
||||
nrfPinObj["clk"] = pin.nrf24_clk;
|
||||
nrfPinObj["cs"] = pin.nrf24_cs;
|
||||
nrfPinObj["en"] = pin.nrf24_en;
|
||||
nrfPinObj["irq"] = pin.nrf24_irq;
|
||||
nrfPinObj["miso"] = pin.nrf24_miso;
|
||||
nrfPinObj["mosi"] = pin.nrf24_mosi;
|
||||
|
||||
JsonObject ethPinObj = curPin.createNestedObject("eth");
|
||||
ethPinObj[F("enabled")] = pin.eth_enabled;
|
||||
ethPinObj[F("phy_addr")] = pin.eth_phy_addr;
|
||||
ethPinObj[F("power")] = pin.eth_power;
|
||||
ethPinObj[F("mdc")] = pin.eth_mdc;
|
||||
ethPinObj[F("mdio")] = pin.eth_mdio;
|
||||
ethPinObj[F("type")] = pin.eth_type;
|
||||
ethPinObj[F("clk_mode")] = pin.eth_clk_mode;
|
||||
ethPinObj["enabled"] = pin.eth_enabled;
|
||||
ethPinObj["phy_addr"] = pin.eth_phy_addr;
|
||||
ethPinObj["power"] = pin.eth_power;
|
||||
ethPinObj["mdc"] = pin.eth_mdc;
|
||||
ethPinObj["mdio"] = pin.eth_mdio;
|
||||
ethPinObj["type"] = pin.eth_type;
|
||||
ethPinObj["clk_mode"] = pin.eth_clk_mode;
|
||||
|
||||
JsonObject displayPinObj = curPin.createNestedObject("display");
|
||||
displayPinObj[F("type")] = pin.display_type;
|
||||
displayPinObj[F("data")] = pin.display_data;
|
||||
displayPinObj[F("clk")] = pin.display_clk;
|
||||
displayPinObj[F("cs")] = pin.display_cs;
|
||||
displayPinObj[F("reset")] = pin.display_reset;
|
||||
displayPinObj["type"] = pin.display_type;
|
||||
displayPinObj["data"] = pin.display_data;
|
||||
displayPinObj["clk"] = pin.display_clk;
|
||||
displayPinObj["cs"] = pin.display_cs;
|
||||
displayPinObj["reset"] = pin.display_reset;
|
||||
|
||||
JsonObject display = root.createNestedObject("display");
|
||||
display[F("rotation")] = config.Display_Rotation;
|
||||
display[F("power_safe")] = config.Display_PowerSafe;
|
||||
display[F("screensaver")] = config.Display_ScreenSaver;
|
||||
display[F("contrast")] = config.Display_Contrast;
|
||||
display["rotation"] = config.Display_Rotation;
|
||||
display["power_safe"] = config.Display_PowerSafe;
|
||||
display["screensaver"] = config.Display_ScreenSaver;
|
||||
display["contrast"] = config.Display_Contrast;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -81,11 +81,11 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -94,8 +94,8 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > MQTT_JSON_DOC_SIZE) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -105,38 +105,38 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(root.containsKey("curPin") || root.containsKey("display"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("curPin")][F("name")].as<String>().length() == 0 || root[F("curPin")][F("name")].as<String>().length() > DEV_MAX_MAPPING_NAME_STRLEN) {
|
||||
retMsg[F("message")] = F("Pin mapping must between 1 and " STR(DEV_MAX_MAPPING_NAME_STRLEN) " characters long!");
|
||||
retMsg[F("code")] = WebApiError::HardwarePinMappingLength;
|
||||
retMsg[F("param")][F("max")] = DEV_MAX_MAPPING_NAME_STRLEN;
|
||||
if (root["curPin"]["name"].as<String>().length() == 0 || root["curPin"]["name"].as<String>().length() > DEV_MAX_MAPPING_NAME_STRLEN) {
|
||||
retMsg["message"] = "Pin mapping must between 1 and " STR(DEV_MAX_MAPPING_NAME_STRLEN) " characters long!";
|
||||
retMsg["code"] = WebApiError::HardwarePinMappingLength;
|
||||
retMsg["param"]["max"] = DEV_MAX_MAPPING_NAME_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
CONFIG_T& config = Configuration.get();
|
||||
bool performRestart = root[F("curPin")][F("name")].as<String>() != config.Dev_PinMapping;
|
||||
bool performRestart = root["curPin"]["name"].as<String>() != config.Dev_PinMapping;
|
||||
|
||||
strlcpy(config.Dev_PinMapping, root[F("curPin")][F("name")].as<String>().c_str(), sizeof(config.Dev_PinMapping));
|
||||
config.Display_Rotation = root[F("display")][F("rotation")].as<uint8_t>();
|
||||
config.Display_PowerSafe = root[F("display")][F("power_safe")].as<bool>();
|
||||
config.Display_ScreenSaver = root[F("display")][F("screensaver")].as<bool>();
|
||||
config.Display_Contrast = root[F("display")][F("contrast")].as<uint8_t>();
|
||||
strlcpy(config.Dev_PinMapping, root["curPin"]["name"].as<String>().c_str(), sizeof(config.Dev_PinMapping));
|
||||
config.Display_Rotation = root["display"]["rotation"].as<uint8_t>();
|
||||
config.Display_PowerSafe = root["display"]["power_safe"].as<bool>();
|
||||
config.Display_ScreenSaver = root["display"]["screensaver"].as<bool>();
|
||||
config.Display_Contrast = root["display"]["contrast"].as<uint8_t>();
|
||||
|
||||
Display.setOrientation(config.Display_Rotation);
|
||||
Display.enablePowerSafe = config.Display_PowerSafe;
|
||||
@ -145,9 +145,9 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
|
||||
|
||||
Configuration.write();
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Settings saved!");
|
||||
retMsg[F("code")] = WebApiError::GenericSuccess;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Settings saved!";
|
||||
retMsg["code"] = WebApiError::GenericSuccess;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
@ -34,18 +34,18 @@ void WebApiDevInfoClass::onDevInfoStatus(AsyncWebServerRequest* request)
|
||||
auto inv = Hoymiles.getInverterByPos(i);
|
||||
|
||||
JsonObject devInfoObj = root[inv->serialString()].createNestedObject();
|
||||
devInfoObj[F("valid_data")] = inv->DevInfo()->getLastUpdate() > 0;
|
||||
devInfoObj[F("fw_bootloader_version")] = inv->DevInfo()->getFwBootloaderVersion();
|
||||
devInfoObj[F("fw_build_version")] = inv->DevInfo()->getFwBuildVersion();
|
||||
devInfoObj[F("hw_part_number")] = inv->DevInfo()->getHwPartNumber();
|
||||
devInfoObj[F("hw_version")] = inv->DevInfo()->getHwVersion();
|
||||
devInfoObj[F("hw_model_name")] = inv->DevInfo()->getHwModelName();
|
||||
devInfoObj[F("max_power")] = inv->DevInfo()->getMaxPower();
|
||||
devInfoObj["valid_data"] = inv->DevInfo()->getLastUpdate() > 0;
|
||||
devInfoObj["fw_bootloader_version"] = inv->DevInfo()->getFwBootloaderVersion();
|
||||
devInfoObj["fw_build_version"] = inv->DevInfo()->getFwBuildVersion();
|
||||
devInfoObj["hw_part_number"] = inv->DevInfo()->getHwPartNumber();
|
||||
devInfoObj["hw_version"] = inv->DevInfo()->getHwVersion();
|
||||
devInfoObj["hw_model_name"] = inv->DevInfo()->getHwModelName();
|
||||
devInfoObj["max_power"] = inv->DevInfo()->getMaxPower();
|
||||
|
||||
char timebuffer[32];
|
||||
const time_t t = inv->DevInfo()->getFwBuildDateTime();
|
||||
std::strftime(timebuffer, sizeof(timebuffer), "%Y-%m-%d %H:%M:%S", gmtime(&t));
|
||||
devInfoObj[F("fw_build_datetime")] = String(timebuffer);
|
||||
devInfoObj["fw_build_datetime"] = String(timebuffer);
|
||||
}
|
||||
|
||||
response->setLength();
|
||||
|
||||
@ -38,9 +38,9 @@ void WebApiDtuClass::onDtuAdminGet(AsyncWebServerRequest* request)
|
||||
snprintf(buffer, sizeof(buffer), "%0x%08x",
|
||||
((uint32_t)((config.Dtu_Serial >> 32) & 0xFFFFFFFF)),
|
||||
((uint32_t)(config.Dtu_Serial & 0xFFFFFFFF)));
|
||||
root[F("dtu_serial")] = buffer;
|
||||
root[F("dtu_pollinterval")] = config.Dtu_PollInterval;
|
||||
root[F("dtu_palevel")] = config.Dtu_PaLevel;
|
||||
root["dtu_serial"] = buffer;
|
||||
root["dtu_pollinterval"] = config.Dtu_PollInterval;
|
||||
root["dtu_palevel"] = config.Dtu_PaLevel;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -54,11 +54,11 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -67,8 +67,8 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -78,40 +78,40 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(root.containsKey("dtu_serial") && root.containsKey("dtu_pollinterval") && root.containsKey("dtu_palevel"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("dtu_serial")].as<uint64_t>() == 0) {
|
||||
retMsg[F("message")] = F("Serial cannot be zero!");
|
||||
retMsg[F("code")] = WebApiError::DtuSerialZero;
|
||||
if (root["dtu_serial"].as<uint64_t>() == 0) {
|
||||
retMsg["message"] = "Serial cannot be zero!";
|
||||
retMsg["code"] = WebApiError::DtuSerialZero;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("dtu_pollinterval")].as<uint32_t>() == 0) {
|
||||
retMsg[F("message")] = F("Poll interval must be greater zero!");
|
||||
retMsg[F("code")] = WebApiError::DtuPollZero;
|
||||
if (root["dtu_pollinterval"].as<uint32_t>() == 0) {
|
||||
retMsg["message"] = "Poll interval must be greater zero!";
|
||||
retMsg["code"] = WebApiError::DtuPollZero;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("dtu_palevel")].as<uint8_t>() > 3) {
|
||||
retMsg[F("message")] = F("Invalid power level setting!");
|
||||
retMsg[F("code")] = WebApiError::DtuInvalidPowerLevel;
|
||||
if (root["dtu_palevel"].as<uint8_t>() > 3) {
|
||||
retMsg["message"] = "Invalid power level setting!";
|
||||
retMsg["code"] = WebApiError::DtuInvalidPowerLevel;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -120,14 +120,14 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
|
||||
CONFIG_T& config = Configuration.get();
|
||||
|
||||
// Interpret the string as a hex value and convert it to uint64_t
|
||||
config.Dtu_Serial = strtoll(root[F("dtu_serial")].as<String>().c_str(), NULL, 16);
|
||||
config.Dtu_PollInterval = root[F("dtu_pollinterval")].as<uint32_t>();
|
||||
config.Dtu_PaLevel = root[F("dtu_palevel")].as<uint8_t>();
|
||||
config.Dtu_Serial = strtoll(root["dtu_serial"].as<String>().c_str(), NULL, 16);
|
||||
config.Dtu_PollInterval = root["dtu_pollinterval"].as<uint32_t>();
|
||||
config.Dtu_PaLevel = root["dtu_palevel"].as<uint8_t>();
|
||||
Configuration.write();
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Settings saved!");
|
||||
retMsg[F("code")] = WebApiError::GenericSuccess;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Settings saved!";
|
||||
retMsg["code"] = WebApiError::GenericSuccess;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
@ -43,7 +43,7 @@ void WebApiEventlogClass::onEventlogStatus(AsyncWebServerRequest* request)
|
||||
uint8_t logEntryCount = inv->EventLog()->getEntryCount();
|
||||
|
||||
root[serial]["count"] = logEntryCount;
|
||||
JsonArray eventsArray = root[serial].createNestedArray(F("events"));
|
||||
JsonArray eventsArray = root[serial].createNestedArray("events");
|
||||
|
||||
for (uint8_t logEntry = 0; logEntry < logEntryCount; logEntry++) {
|
||||
JsonObject eventsObject = eventsArray.createNestedObject();
|
||||
@ -51,10 +51,10 @@ void WebApiEventlogClass::onEventlogStatus(AsyncWebServerRequest* request)
|
||||
AlarmLogEntry_t entry;
|
||||
inv->EventLog()->getLogEntry(logEntry, &entry);
|
||||
|
||||
eventsObject[F("message_id")] = entry.MessageId;
|
||||
eventsObject[F("message")] = entry.Message;
|
||||
eventsObject[F("start_time")] = entry.StartTime;
|
||||
eventsObject[F("end_time")] = entry.EndTime;
|
||||
eventsObject["message_id"] = entry.MessageId;
|
||||
eventsObject["message"] = entry.Message;
|
||||
eventsObject["start_time"] = entry.StartTime;
|
||||
eventsObject["end_time"] = entry.EndTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -35,34 +35,34 @@ void WebApiInverterClass::onInverterList(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 4096U);
|
||||
JsonObject root = response->getRoot();
|
||||
JsonArray data = root.createNestedArray(F("inverter"));
|
||||
JsonArray data = root.createNestedArray("inverter");
|
||||
|
||||
const CONFIG_T& config = Configuration.get();
|
||||
|
||||
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
|
||||
if (config.Inverter[i].Serial > 0) {
|
||||
JsonObject obj = data.createNestedObject();
|
||||
obj[F("id")] = i;
|
||||
obj[F("name")] = String(config.Inverter[i].Name);
|
||||
obj["id"] = i;
|
||||
obj["name"] = String(config.Inverter[i].Name);
|
||||
|
||||
// Inverter Serial is read as HEX
|
||||
char buffer[sizeof(uint64_t) * 8 + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%0x%08x",
|
||||
((uint32_t)((config.Inverter[i].Serial >> 32) & 0xFFFFFFFF)),
|
||||
((uint32_t)(config.Inverter[i].Serial & 0xFFFFFFFF)));
|
||||
obj[F("serial")] = buffer;
|
||||
obj[F("poll_enable")] = config.Inverter[i].Poll_Enable;
|
||||
obj[F("poll_enable_night")] = config.Inverter[i].Poll_Enable_Night;
|
||||
obj[F("command_enable")] = config.Inverter[i].Command_Enable;
|
||||
obj[F("command_enable_night")] = config.Inverter[i].Command_Enable_Night;
|
||||
obj["serial"] = buffer;
|
||||
obj["poll_enable"] = config.Inverter[i].Poll_Enable;
|
||||
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;
|
||||
|
||||
auto inv = Hoymiles.getInverterBySerial(config.Inverter[i].Serial);
|
||||
uint8_t max_channels;
|
||||
if (inv == nullptr) {
|
||||
obj[F("type")] = F("Unknown");
|
||||
obj["type"] = "Unknown";
|
||||
max_channels = INV_MAX_CHAN_COUNT;
|
||||
} else {
|
||||
obj[F("type")] = inv->typeName();
|
||||
obj["type"] = inv->typeName();
|
||||
max_channels = inv->Statistics()->getChannelsByType(TYPE_DC).size();
|
||||
}
|
||||
|
||||
@ -88,11 +88,11 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -101,8 +101,8 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -112,33 +112,33 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(root.containsKey("serial") && root.containsKey("name"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("serial")].as<uint64_t>() == 0) {
|
||||
retMsg[F("message")] = F("Serial must be a number > 0!");
|
||||
retMsg[F("code")] = WebApiError::InverterSerialZero;
|
||||
if (root["serial"].as<uint64_t>() == 0) {
|
||||
retMsg["message"] = "Serial must be a number > 0!";
|
||||
retMsg["code"] = WebApiError::InverterSerialZero;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("name")].as<String>().length() == 0 || root[F("name")].as<String>().length() > INV_MAX_NAME_STRLEN) {
|
||||
retMsg[F("message")] = F("Name must between 1 and " STR(INV_MAX_NAME_STRLEN) " characters long!");
|
||||
retMsg[F("code")] = WebApiError::InverterNameLength;
|
||||
retMsg[F("param")][F("max")] = INV_MAX_NAME_STRLEN;
|
||||
if (root["name"].as<String>().length() == 0 || root["name"].as<String>().length() > INV_MAX_NAME_STRLEN) {
|
||||
retMsg["message"] = "Name must between 1 and " STR(INV_MAX_NAME_STRLEN) " characters long!";
|
||||
retMsg["code"] = WebApiError::InverterNameLength;
|
||||
retMsg["param"]["max"] = INV_MAX_NAME_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -147,23 +147,23 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
|
||||
INVERTER_CONFIG_T* inverter = Configuration.getFreeInverterSlot();
|
||||
|
||||
if (!inverter) {
|
||||
retMsg[F("message")] = F("Only " STR(INV_MAX_COUNT) " inverters are supported!");
|
||||
retMsg[F("code")] = WebApiError::InverterCount;
|
||||
retMsg[F("param")][F("max")] = INV_MAX_COUNT;
|
||||
retMsg["message"] = "Only " STR(INV_MAX_COUNT) " inverters are supported!";
|
||||
retMsg["code"] = WebApiError::InverterCount;
|
||||
retMsg["param"]["max"] = INV_MAX_COUNT;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
// Interpret the string as a hex value and convert it to uint64_t
|
||||
inverter->Serial = strtoll(root[F("serial")].as<String>().c_str(), NULL, 16);
|
||||
inverter->Serial = strtoll(root["serial"].as<String>().c_str(), NULL, 16);
|
||||
|
||||
strncpy(inverter->Name, root[F("name")].as<String>().c_str(), INV_MAX_NAME_STRLEN);
|
||||
strncpy(inverter->Name, root["name"].as<String>().c_str(), INV_MAX_NAME_STRLEN);
|
||||
Configuration.write();
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Inverter created!");
|
||||
retMsg[F("code")] = WebApiError::InverterAdded;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Inverter created!";
|
||||
retMsg["code"] = WebApiError::InverterAdded;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -187,11 +187,11 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -200,8 +200,8 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -211,82 +211,82 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(root.containsKey("id") && root.containsKey("serial") && root.containsKey("name") && root.containsKey("channel"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("id")].as<uint8_t>() > INV_MAX_COUNT - 1) {
|
||||
retMsg[F("message")] = F("Invalid ID specified!");
|
||||
retMsg[F("code")] = WebApiError::InverterInvalidId;
|
||||
if (root["id"].as<uint8_t>() > INV_MAX_COUNT - 1) {
|
||||
retMsg["message"] = "Invalid ID specified!";
|
||||
retMsg["code"] = WebApiError::InverterInvalidId;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("serial")].as<uint64_t>() == 0) {
|
||||
retMsg[F("message")] = F("Serial must be a number > 0!");
|
||||
retMsg[F("code")] = WebApiError::InverterSerialZero;
|
||||
if (root["serial"].as<uint64_t>() == 0) {
|
||||
retMsg["message"] = "Serial must be a number > 0!";
|
||||
retMsg["code"] = WebApiError::InverterSerialZero;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("name")].as<String>().length() == 0 || root[F("name")].as<String>().length() > INV_MAX_NAME_STRLEN) {
|
||||
retMsg[F("message")] = F("Name must between 1 and " STR(INV_MAX_NAME_STRLEN) " characters long!");
|
||||
retMsg[F("code")] = WebApiError::InverterNameLength;
|
||||
retMsg[F("param")][F("max")] = INV_MAX_NAME_STRLEN;
|
||||
if (root["name"].as<String>().length() == 0 || root["name"].as<String>().length() > INV_MAX_NAME_STRLEN) {
|
||||
retMsg["message"] = "Name must between 1 and " STR(INV_MAX_NAME_STRLEN) " characters long!";
|
||||
retMsg["code"] = WebApiError::InverterNameLength;
|
||||
retMsg["param"]["max"] = INV_MAX_NAME_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
JsonArray channelArray = root[F("channel")].as<JsonArray>();
|
||||
JsonArray channelArray = root["channel"].as<JsonArray>();
|
||||
if (channelArray.size() == 0 || channelArray.size() > INV_MAX_CHAN_COUNT) {
|
||||
retMsg[F("message")] = F("Invalid amount of max channel setting given!");
|
||||
retMsg[F("code")] = WebApiError::InverterInvalidMaxChannel;
|
||||
retMsg["message"] = "Invalid amount of max channel setting given!";
|
||||
retMsg["code"] = WebApiError::InverterInvalidMaxChannel;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
INVERTER_CONFIG_T& inverter = Configuration.get().Inverter[root[F("id")].as<uint8_t>()];
|
||||
INVERTER_CONFIG_T& inverter = Configuration.get().Inverter[root["id"].as<uint8_t>()];
|
||||
|
||||
uint64_t new_serial = strtoll(root[F("serial")].as<String>().c_str(), NULL, 16);
|
||||
uint64_t new_serial = strtoll(root["serial"].as<String>().c_str(), NULL, 16);
|
||||
uint64_t old_serial = inverter.Serial;
|
||||
|
||||
// Interpret the string as a hex value and convert it to uint64_t
|
||||
inverter.Serial = new_serial;
|
||||
strncpy(inverter.Name, root[F("name")].as<String>().c_str(), INV_MAX_NAME_STRLEN);
|
||||
strncpy(inverter.Name, root["name"].as<String>().c_str(), INV_MAX_NAME_STRLEN);
|
||||
|
||||
uint8_t arrayCount = 0;
|
||||
for (JsonVariant channel : channelArray) {
|
||||
inverter.channel[arrayCount].MaxChannelPower = channel[F("max_power")].as<uint16_t>();
|
||||
inverter.channel[arrayCount].YieldTotalOffset = channel[F("yield_total_offset")].as<float>();
|
||||
strncpy(inverter.channel[arrayCount].Name, channel[F("name")] | "", sizeof(inverter.channel[arrayCount].Name));
|
||||
inverter.Poll_Enable = root[F("poll_enable")] | true;
|
||||
inverter.Poll_Enable_Night = root[F("poll_enable_night")] | true;
|
||||
inverter.Command_Enable = root[F("command_enable")] | true;
|
||||
inverter.Command_Enable_Night = root[F("command_enable_night")] | true;
|
||||
inverter.channel[arrayCount].MaxChannelPower = channel["max_power"].as<uint16_t>();
|
||||
inverter.channel[arrayCount].YieldTotalOffset = channel["yield_total_offset"].as<float>();
|
||||
strncpy(inverter.channel[arrayCount].Name, channel["name"] | "", sizeof(inverter.channel[arrayCount].Name));
|
||||
inverter.Poll_Enable = root["poll_enable"] | true;
|
||||
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;
|
||||
|
||||
arrayCount++;
|
||||
}
|
||||
|
||||
Configuration.write();
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("code")] = WebApiError::InverterChanged;
|
||||
retMsg[F("message")] = F("Inverter changed!");
|
||||
retMsg["type"] = "success";
|
||||
retMsg["code"] = WebApiError::InverterChanged;
|
||||
retMsg["message"] = "Inverter changed!";
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -325,11 +325,11 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -338,8 +338,8 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -349,30 +349,30 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(root.containsKey("id"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("id")].as<uint8_t>() > INV_MAX_COUNT - 1) {
|
||||
retMsg[F("message")] = F("Invalid ID specified!");
|
||||
retMsg[F("code")] = WebApiError::InverterInvalidId;
|
||||
if (root["id"].as<uint8_t>() > INV_MAX_COUNT - 1) {
|
||||
retMsg["message"] = "Invalid ID specified!";
|
||||
retMsg["code"] = WebApiError::InverterInvalidId;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t inverter_id = root[F("id")].as<uint8_t>();
|
||||
uint8_t inverter_id = root["id"].as<uint8_t>();
|
||||
INVERTER_CONFIG_T& inverter = Configuration.get().Inverter[inverter_id];
|
||||
|
||||
Hoymiles.removeInverterBySerial(inverter.Serial);
|
||||
@ -381,9 +381,9 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
|
||||
strncpy(inverter.Name, "", sizeof(inverter.Name));
|
||||
Configuration.write();
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Inverter deleted!");
|
||||
retMsg[F("code")] = WebApiError::InverterDeleted;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Inverter deleted!";
|
||||
retMsg["code"] = WebApiError::InverterDeleted;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
@ -63,11 +63,11 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -76,8 +76,8 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -87,8 +87,8 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -97,50 +97,50 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
||||
if (!(root.containsKey("serial")
|
||||
&& root.containsKey("limit_value")
|
||||
&& root.containsKey("limit_type"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("serial")].as<uint64_t>() == 0) {
|
||||
retMsg[F("message")] = F("Serial must be a number > 0!");
|
||||
retMsg[F("code")] = WebApiError::LimitSerialZero;
|
||||
if (root["serial"].as<uint64_t>() == 0) {
|
||||
retMsg["message"] = "Serial must be a number > 0!";
|
||||
retMsg["code"] = WebApiError::LimitSerialZero;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("limit_value")].as<uint16_t>() == 0 || root[F("limit_value")].as<uint16_t>() > 1500) {
|
||||
retMsg[F("message")] = F("Limit must between 1 and 1500!");
|
||||
retMsg[F("code")] = WebApiError::LimitInvalidLimit;
|
||||
retMsg[F("param")][F("max")] = 1500;
|
||||
if (root["limit_value"].as<uint16_t>() == 0 || root["limit_value"].as<uint16_t>() > 1500) {
|
||||
retMsg["message"] = "Limit must between 1 and 1500!";
|
||||
retMsg["code"] = WebApiError::LimitInvalidLimit;
|
||||
retMsg["param"]["max"] = 1500;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!((root[F("limit_type")].as<uint16_t>() == PowerLimitControlType::AbsolutNonPersistent)
|
||||
|| (root[F("limit_type")].as<uint16_t>() == PowerLimitControlType::AbsolutPersistent)
|
||||
|| (root[F("limit_type")].as<uint16_t>() == PowerLimitControlType::RelativNonPersistent)
|
||||
|| (root[F("limit_type")].as<uint16_t>() == PowerLimitControlType::RelativPersistent))) {
|
||||
if (!((root["limit_type"].as<uint16_t>() == PowerLimitControlType::AbsolutNonPersistent)
|
||||
|| (root["limit_type"].as<uint16_t>() == PowerLimitControlType::AbsolutPersistent)
|
||||
|| (root["limit_type"].as<uint16_t>() == PowerLimitControlType::RelativNonPersistent)
|
||||
|| (root["limit_type"].as<uint16_t>() == PowerLimitControlType::RelativPersistent))) {
|
||||
|
||||
retMsg[F("message")] = F("Invalid type specified!");
|
||||
retMsg[F("code")] = WebApiError::LimitInvalidType;
|
||||
retMsg["message"] = "Invalid type specified!";
|
||||
retMsg["code"] = WebApiError::LimitInvalidType;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t serial = strtoll(root[F("serial")].as<String>().c_str(), NULL, 16);
|
||||
uint16_t limit = root[F("limit_value")].as<uint16_t>();
|
||||
PowerLimitControlType type = root[F("limit_type")].as<PowerLimitControlType>();
|
||||
uint64_t serial = strtoll(root["serial"].as<String>().c_str(), NULL, 16);
|
||||
uint16_t limit = root["limit_value"].as<uint16_t>();
|
||||
PowerLimitControlType type = root["limit_type"].as<PowerLimitControlType>();
|
||||
|
||||
auto inv = Hoymiles.getInverterBySerial(serial);
|
||||
if (inv == nullptr) {
|
||||
retMsg[F("message")] = F("Invalid inverter specified!");
|
||||
retMsg[F("code")] = WebApiError::LimitInvalidInverter;
|
||||
retMsg["message"] = "Invalid inverter specified!";
|
||||
retMsg["code"] = WebApiError::LimitInvalidInverter;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -148,9 +148,9 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
|
||||
|
||||
inv->sendActivePowerControlRequest(Hoymiles.getRadio(), limit, type);
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Settings saved!");
|
||||
retMsg[F("code")] = WebApiError::GenericSuccess;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Settings saved!";
|
||||
retMsg["code"] = WebApiError::GenericSuccess;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
@ -29,11 +29,11 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -42,8 +42,8 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > MQTT_JSON_DOC_SIZE) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -53,25 +53,25 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(root.containsKey("reboot"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("reboot")].as<bool>()) {
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Reboot triggered!");
|
||||
retMsg[F("code")] = WebApiError::MaintenanceRebootTriggered;
|
||||
if (root["reboot"].as<bool>()) {
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Reboot triggered!";
|
||||
retMsg["code"] = WebApiError::MaintenanceRebootTriggered;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -80,8 +80,8 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)
|
||||
yield();
|
||||
ESP.restart();
|
||||
} else {
|
||||
retMsg[F("message")] = F("Reboot cancled!");
|
||||
retMsg[F("code")] = WebApiError::MaintenanceRebootCancled;
|
||||
retMsg["message"] = "Reboot cancled!";
|
||||
retMsg["code"] = WebApiError::MaintenanceRebootCancled;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
@ -36,22 +36,22 @@ void WebApiMqttClass::onMqttStatus(AsyncWebServerRequest* request)
|
||||
JsonObject root = response->getRoot();
|
||||
const CONFIG_T& config = Configuration.get();
|
||||
|
||||
root[F("mqtt_enabled")] = config.Mqtt_Enabled;
|
||||
root[F("mqtt_hostname")] = config.Mqtt_Hostname;
|
||||
root[F("mqtt_port")] = config.Mqtt_Port;
|
||||
root[F("mqtt_username")] = config.Mqtt_Username;
|
||||
root[F("mqtt_topic")] = config.Mqtt_Topic;
|
||||
root[F("mqtt_connected")] = MqttSettings.getConnected();
|
||||
root[F("mqtt_retain")] = config.Mqtt_Retain;
|
||||
root[F("mqtt_tls")] = config.Mqtt_Tls;
|
||||
root[F("mqtt_root_ca_cert_info")] = getRootCaCertInfo(config.Mqtt_RootCaCert);
|
||||
root[F("mqtt_lwt_topic")] = String(config.Mqtt_Topic) + config.Mqtt_LwtTopic;
|
||||
root[F("mqtt_publish_interval")] = config.Mqtt_PublishInterval;
|
||||
root[F("mqtt_hass_enabled")] = config.Mqtt_Hass_Enabled;
|
||||
root[F("mqtt_hass_expire")] = config.Mqtt_Hass_Expire;
|
||||
root[F("mqtt_hass_retain")] = config.Mqtt_Hass_Retain;
|
||||
root[F("mqtt_hass_topic")] = config.Mqtt_Hass_Topic;
|
||||
root[F("mqtt_hass_individualpanels")] = config.Mqtt_Hass_IndividualPanels;
|
||||
root["mqtt_enabled"] = config.Mqtt_Enabled;
|
||||
root["mqtt_hostname"] = config.Mqtt_Hostname;
|
||||
root["mqtt_port"] = config.Mqtt_Port;
|
||||
root["mqtt_username"] = config.Mqtt_Username;
|
||||
root["mqtt_topic"] = config.Mqtt_Topic;
|
||||
root["mqtt_connected"] = MqttSettings.getConnected();
|
||||
root["mqtt_retain"] = config.Mqtt_Retain;
|
||||
root["mqtt_tls"] = config.Mqtt_Tls;
|
||||
root["mqtt_root_ca_cert_info"] = getRootCaCertInfo(config.Mqtt_RootCaCert);
|
||||
root["mqtt_lwt_topic"] = String(config.Mqtt_Topic) + config.Mqtt_LwtTopic;
|
||||
root["mqtt_publish_interval"] = config.Mqtt_PublishInterval;
|
||||
root["mqtt_hass_enabled"] = config.Mqtt_Hass_Enabled;
|
||||
root["mqtt_hass_expire"] = config.Mqtt_Hass_Expire;
|
||||
root["mqtt_hass_retain"] = config.Mqtt_Hass_Retain;
|
||||
root["mqtt_hass_topic"] = config.Mqtt_Hass_Topic;
|
||||
root["mqtt_hass_individualpanels"] = config.Mqtt_Hass_IndividualPanels;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -67,24 +67,24 @@ void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request)
|
||||
JsonObject root = response->getRoot();
|
||||
const CONFIG_T& config = Configuration.get();
|
||||
|
||||
root[F("mqtt_enabled")] = config.Mqtt_Enabled;
|
||||
root[F("mqtt_hostname")] = config.Mqtt_Hostname;
|
||||
root[F("mqtt_port")] = config.Mqtt_Port;
|
||||
root[F("mqtt_username")] = config.Mqtt_Username;
|
||||
root[F("mqtt_password")] = config.Mqtt_Password;
|
||||
root[F("mqtt_topic")] = config.Mqtt_Topic;
|
||||
root[F("mqtt_retain")] = config.Mqtt_Retain;
|
||||
root[F("mqtt_tls")] = config.Mqtt_Tls;
|
||||
root[F("mqtt_root_ca_cert")] = config.Mqtt_RootCaCert;
|
||||
root[F("mqtt_lwt_topic")] = config.Mqtt_LwtTopic;
|
||||
root[F("mqtt_lwt_online")] = config.Mqtt_LwtValue_Online;
|
||||
root[F("mqtt_lwt_offline")] = config.Mqtt_LwtValue_Offline;
|
||||
root[F("mqtt_publish_interval")] = config.Mqtt_PublishInterval;
|
||||
root[F("mqtt_hass_enabled")] = config.Mqtt_Hass_Enabled;
|
||||
root[F("mqtt_hass_expire")] = config.Mqtt_Hass_Expire;
|
||||
root[F("mqtt_hass_retain")] = config.Mqtt_Hass_Retain;
|
||||
root[F("mqtt_hass_topic")] = config.Mqtt_Hass_Topic;
|
||||
root[F("mqtt_hass_individualpanels")] = config.Mqtt_Hass_IndividualPanels;
|
||||
root["mqtt_enabled"] = config.Mqtt_Enabled;
|
||||
root["mqtt_hostname"] = config.Mqtt_Hostname;
|
||||
root["mqtt_port"] = config.Mqtt_Port;
|
||||
root["mqtt_username"] = config.Mqtt_Username;
|
||||
root["mqtt_password"] = config.Mqtt_Password;
|
||||
root["mqtt_topic"] = config.Mqtt_Topic;
|
||||
root["mqtt_retain"] = config.Mqtt_Retain;
|
||||
root["mqtt_tls"] = config.Mqtt_Tls;
|
||||
root["mqtt_root_ca_cert"] = config.Mqtt_RootCaCert;
|
||||
root["mqtt_lwt_topic"] = config.Mqtt_LwtTopic;
|
||||
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_hass_enabled"] = config.Mqtt_Hass_Enabled;
|
||||
root["mqtt_hass_expire"] = config.Mqtt_Hass_Expire;
|
||||
root["mqtt_hass_retain"] = config.Mqtt_Hass_Retain;
|
||||
root["mqtt_hass_topic"] = config.Mqtt_Hass_Topic;
|
||||
root["mqtt_hass_individualpanels"] = config.Mqtt_Hass_IndividualPanels;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -98,11 +98,11 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -111,8 +111,8 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > MQTT_JSON_DOC_SIZE) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -122,8 +122,8 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -146,139 +146,139 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
||||
&& root.containsKey("mqtt_hass_retain")
|
||||
&& root.containsKey("mqtt_hass_topic")
|
||||
&& root.containsKey("mqtt_hass_individualpanels"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("mqtt_enabled")].as<bool>()) {
|
||||
if (root[F("mqtt_hostname")].as<String>().length() == 0 || root[F("mqtt_hostname")].as<String>().length() > MQTT_MAX_HOSTNAME_STRLEN) {
|
||||
retMsg[F("message")] = F("MqTT Server must between 1 and " STR(MQTT_MAX_HOSTNAME_STRLEN) " characters long!");
|
||||
retMsg[F("code")] = WebApiError::MqttHostnameLength;
|
||||
retMsg[F("param")][F("max")] = MQTT_MAX_HOSTNAME_STRLEN;
|
||||
if (root["mqtt_enabled"].as<bool>()) {
|
||||
if (root["mqtt_hostname"].as<String>().length() == 0 || root["mqtt_hostname"].as<String>().length() > MQTT_MAX_HOSTNAME_STRLEN) {
|
||||
retMsg["message"] = "MqTT Server must between 1 and " STR(MQTT_MAX_HOSTNAME_STRLEN) " characters long!";
|
||||
retMsg["code"] = WebApiError::MqttHostnameLength;
|
||||
retMsg["param"]["max"] = MQTT_MAX_HOSTNAME_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("mqtt_username")].as<String>().length() > MQTT_MAX_USERNAME_STRLEN) {
|
||||
retMsg[F("message")] = F("Username must not longer then " STR(MQTT_MAX_USERNAME_STRLEN) " characters!");
|
||||
retMsg[F("code")] = WebApiError::MqttUsernameLength;
|
||||
retMsg[F("param")][F("max")] = MQTT_MAX_USERNAME_STRLEN;
|
||||
if (root["mqtt_username"].as<String>().length() > MQTT_MAX_USERNAME_STRLEN) {
|
||||
retMsg["message"] = "Username must not longer then " STR(MQTT_MAX_USERNAME_STRLEN) " characters!";
|
||||
retMsg["code"] = WebApiError::MqttUsernameLength;
|
||||
retMsg["param"]["max"] = MQTT_MAX_USERNAME_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
if (root[F("mqtt_password")].as<String>().length() > MQTT_MAX_PASSWORD_STRLEN) {
|
||||
retMsg[F("message")] = F("Password must not longer then " STR(MQTT_MAX_PASSWORD_STRLEN) " characters!");
|
||||
retMsg[F("code")] = WebApiError::MqttPasswordLength;
|
||||
retMsg[F("param")][F("max")] = MQTT_MAX_PASSWORD_STRLEN;
|
||||
if (root["mqtt_password"].as<String>().length() > MQTT_MAX_PASSWORD_STRLEN) {
|
||||
retMsg["message"] = "Password must not longer then " STR(MQTT_MAX_PASSWORD_STRLEN) " characters!";
|
||||
retMsg["code"] = WebApiError::MqttPasswordLength;
|
||||
retMsg["param"]["max"] = MQTT_MAX_PASSWORD_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
if (root[F("mqtt_topic")].as<String>().length() > MQTT_MAX_TOPIC_STRLEN) {
|
||||
retMsg[F("message")] = F("Topic must not longer then " STR(MQTT_MAX_TOPIC_STRLEN) " characters!");
|
||||
retMsg[F("code")] = WebApiError::MqttTopicLength;
|
||||
retMsg[F("param")][F("max")] = MQTT_MAX_TOPIC_STRLEN;
|
||||
if (root["mqtt_topic"].as<String>().length() > MQTT_MAX_TOPIC_STRLEN) {
|
||||
retMsg["message"] = "Topic must not longer then " STR(MQTT_MAX_TOPIC_STRLEN) " characters!";
|
||||
retMsg["code"] = WebApiError::MqttTopicLength;
|
||||
retMsg["param"]["max"] = MQTT_MAX_TOPIC_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("mqtt_topic")].as<String>().indexOf(' ') != -1) {
|
||||
retMsg[F("message")] = F("Topic must not contain space characters!");
|
||||
retMsg[F("code")] = WebApiError::MqttTopicCharacter;
|
||||
if (root["mqtt_topic"].as<String>().indexOf(' ') != -1) {
|
||||
retMsg["message"] = "Topic must not contain space characters!";
|
||||
retMsg["code"] = WebApiError::MqttTopicCharacter;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!root[F("mqtt_topic")].as<String>().endsWith("/")) {
|
||||
retMsg[F("message")] = F("Topic must end with slash (/)!");
|
||||
retMsg[F("code")] = WebApiError::MqttTopicTrailingSlash;
|
||||
if (!root["mqtt_topic"].as<String>().endsWith("/")) {
|
||||
retMsg["message"] = "Topic must end with slash (/)!";
|
||||
retMsg["code"] = WebApiError::MqttTopicTrailingSlash;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("mqtt_port")].as<uint>() == 0 || root[F("mqtt_port")].as<uint>() > 65535) {
|
||||
retMsg[F("message")] = F("Port must be a number between 1 and 65535!");
|
||||
retMsg[F("code")] = WebApiError::MqttPort;
|
||||
if (root["mqtt_port"].as<uint>() == 0 || root["mqtt_port"].as<uint>() > 65535) {
|
||||
retMsg["message"] = "Port must be a number between 1 and 65535!";
|
||||
retMsg["code"] = WebApiError::MqttPort;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("mqtt_root_ca_cert")].as<String>().length() > MQTT_MAX_ROOT_CA_CERT_STRLEN) {
|
||||
retMsg[F("message")] = F("Certificate must not longer then " STR(MQTT_MAX_ROOT_CA_CERT_STRLEN) " characters!");
|
||||
retMsg[F("code")] = WebApiError::MqttCertificateLength;
|
||||
retMsg[F("param")][F("max")] = MQTT_MAX_ROOT_CA_CERT_STRLEN;
|
||||
if (root["mqtt_root_ca_cert"].as<String>().length() > MQTT_MAX_ROOT_CA_CERT_STRLEN) {
|
||||
retMsg["message"] = "Certificate must not longer then " STR(MQTT_MAX_ROOT_CA_CERT_STRLEN) " characters!";
|
||||
retMsg["code"] = WebApiError::MqttCertificateLength;
|
||||
retMsg["param"]["max"] = MQTT_MAX_ROOT_CA_CERT_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("mqtt_lwt_topic")].as<String>().length() > MQTT_MAX_TOPIC_STRLEN) {
|
||||
retMsg[F("message")] = F("LWT topic must not longer then " STR(MQTT_MAX_TOPIC_STRLEN) " characters!");
|
||||
retMsg[F("code")] = WebApiError::MqttLwtTopicLength;
|
||||
retMsg[F("param")][F("max")] = MQTT_MAX_TOPIC_STRLEN;
|
||||
if (root["mqtt_lwt_topic"].as<String>().length() > MQTT_MAX_TOPIC_STRLEN) {
|
||||
retMsg["message"] = "LWT topic must not longer then " STR(MQTT_MAX_TOPIC_STRLEN) " characters!";
|
||||
retMsg["code"] = WebApiError::MqttLwtTopicLength;
|
||||
retMsg["param"]["max"] = MQTT_MAX_TOPIC_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("mqtt_lwt_topic")].as<String>().indexOf(' ') != -1) {
|
||||
retMsg[F("message")] = F("LWT topic must not contain space characters!");
|
||||
retMsg[F("code")] = WebApiError::MqttLwtTopicCharacter;
|
||||
if (root["mqtt_lwt_topic"].as<String>().indexOf(' ') != -1) {
|
||||
retMsg["message"] = "LWT topic must not contain space characters!";
|
||||
retMsg["code"] = WebApiError::MqttLwtTopicCharacter;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("mqtt_lwt_online")].as<String>().length() > MQTT_MAX_LWTVALUE_STRLEN) {
|
||||
retMsg[F("message")] = F("LWT online value must not longer then " STR(MQTT_MAX_LWTVALUE_STRLEN) " characters!");
|
||||
retMsg[F("code")] = WebApiError::MqttLwtOnlineLength;
|
||||
retMsg[F("param")][F("max")] = MQTT_MAX_LWTVALUE_STRLEN;
|
||||
if (root["mqtt_lwt_online"].as<String>().length() > MQTT_MAX_LWTVALUE_STRLEN) {
|
||||
retMsg["message"] = "LWT online value must not longer then " STR(MQTT_MAX_LWTVALUE_STRLEN) " characters!";
|
||||
retMsg["code"] = WebApiError::MqttLwtOnlineLength;
|
||||
retMsg["param"]["max"] = MQTT_MAX_LWTVALUE_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("mqtt_lwt_offline")].as<String>().length() > MQTT_MAX_LWTVALUE_STRLEN) {
|
||||
retMsg[F("message")] = F("LWT offline value must not longer then " STR(MQTT_MAX_LWTVALUE_STRLEN) " characters!");
|
||||
retMsg[F("code")] = WebApiError::MqttLwtOfflineLength;
|
||||
retMsg[F("param")][F("max")] = MQTT_MAX_LWTVALUE_STRLEN;
|
||||
if (root["mqtt_lwt_offline"].as<String>().length() > MQTT_MAX_LWTVALUE_STRLEN) {
|
||||
retMsg["message"] = "LWT offline value must not longer then " STR(MQTT_MAX_LWTVALUE_STRLEN) " characters!";
|
||||
retMsg["code"] = WebApiError::MqttLwtOfflineLength;
|
||||
retMsg["param"]["max"] = MQTT_MAX_LWTVALUE_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("mqtt_publish_interval")].as<uint32_t>() < 5 || root[F("mqtt_publish_interval")].as<uint32_t>() > 65535) {
|
||||
retMsg[F("message")] = F("Publish interval must be a number between 5 and 65535!");
|
||||
retMsg[F("code")] = WebApiError::MqttPublishInterval;
|
||||
retMsg[F("param")][F("min")] = 5;
|
||||
retMsg[F("param")][F("max")] = 65535;
|
||||
if (root["mqtt_publish_interval"].as<uint32_t>() < 5 || root["mqtt_publish_interval"].as<uint32_t>() > 65535) {
|
||||
retMsg["message"] = "Publish interval must be a number between 5 and 65535!";
|
||||
retMsg["code"] = WebApiError::MqttPublishInterval;
|
||||
retMsg["param"]["min"] = 5;
|
||||
retMsg["param"]["max"] = 65535;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("mqtt_hass_enabled")].as<bool>()) {
|
||||
if (root[F("mqtt_hass_topic")].as<String>().length() > MQTT_MAX_TOPIC_STRLEN) {
|
||||
retMsg[F("message")] = F("Hass topic must not longer then " STR(MQTT_MAX_TOPIC_STRLEN) " characters!");
|
||||
retMsg[F("code")] = WebApiError::MqttHassTopicLength;
|
||||
retMsg[F("param")][F("max")] = MQTT_MAX_TOPIC_STRLEN;
|
||||
if (root["mqtt_hass_enabled"].as<bool>()) {
|
||||
if (root["mqtt_hass_topic"].as<String>().length() > MQTT_MAX_TOPIC_STRLEN) {
|
||||
retMsg["message"] = "Hass topic must not longer then " STR(MQTT_MAX_TOPIC_STRLEN) " characters!";
|
||||
retMsg["code"] = WebApiError::MqttHassTopicLength;
|
||||
retMsg["param"]["max"] = MQTT_MAX_TOPIC_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("mqtt_hass_topic")].as<String>().indexOf(' ') != -1) {
|
||||
retMsg[F("message")] = F("Hass topic must not contain space characters!");
|
||||
retMsg[F("code")] = WebApiError::MqttHassTopicCharacter;
|
||||
if (root["mqtt_hass_topic"].as<String>().indexOf(' ') != -1) {
|
||||
retMsg["message"] = "Hass topic must not contain space characters!";
|
||||
retMsg["code"] = WebApiError::MqttHassTopicCharacter;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -287,29 +287,29 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
||||
}
|
||||
|
||||
CONFIG_T& config = Configuration.get();
|
||||
config.Mqtt_Enabled = root[F("mqtt_enabled")].as<bool>();
|
||||
config.Mqtt_Retain = root[F("mqtt_retain")].as<bool>();
|
||||
config.Mqtt_Tls = root[F("mqtt_tls")].as<bool>();
|
||||
strlcpy(config.Mqtt_RootCaCert, root[F("mqtt_root_ca_cert")].as<String>().c_str(), sizeof(config.Mqtt_RootCaCert));
|
||||
config.Mqtt_Port = root[F("mqtt_port")].as<uint>();
|
||||
strlcpy(config.Mqtt_Hostname, root[F("mqtt_hostname")].as<String>().c_str(), sizeof(config.Mqtt_Hostname));
|
||||
strlcpy(config.Mqtt_Username, root[F("mqtt_username")].as<String>().c_str(), sizeof(config.Mqtt_Username));
|
||||
strlcpy(config.Mqtt_Password, root[F("mqtt_password")].as<String>().c_str(), sizeof(config.Mqtt_Password));
|
||||
strlcpy(config.Mqtt_Topic, root[F("mqtt_topic")].as<String>().c_str(), sizeof(config.Mqtt_Topic));
|
||||
strlcpy(config.Mqtt_LwtTopic, root[F("mqtt_lwt_topic")].as<String>().c_str(), sizeof(config.Mqtt_LwtTopic));
|
||||
strlcpy(config.Mqtt_LwtValue_Online, root[F("mqtt_lwt_online")].as<String>().c_str(), sizeof(config.Mqtt_LwtValue_Online));
|
||||
strlcpy(config.Mqtt_LwtValue_Offline, root[F("mqtt_lwt_offline")].as<String>().c_str(), sizeof(config.Mqtt_LwtValue_Offline));
|
||||
config.Mqtt_PublishInterval = root[F("mqtt_publish_interval")].as<uint32_t>();
|
||||
config.Mqtt_Hass_Enabled = root[F("mqtt_hass_enabled")].as<bool>();
|
||||
config.Mqtt_Hass_Expire = root[F("mqtt_hass_expire")].as<bool>();
|
||||
config.Mqtt_Hass_Retain = root[F("mqtt_hass_retain")].as<bool>();
|
||||
config.Mqtt_Hass_IndividualPanels = root[F("mqtt_hass_individualpanels")].as<bool>();
|
||||
strlcpy(config.Mqtt_Hass_Topic, root[F("mqtt_hass_topic")].as<String>().c_str(), sizeof(config.Mqtt_Hass_Topic));
|
||||
config.Mqtt_Enabled = root["mqtt_enabled"].as<bool>();
|
||||
config.Mqtt_Retain = root["mqtt_retain"].as<bool>();
|
||||
config.Mqtt_Tls = root["mqtt_tls"].as<bool>();
|
||||
strlcpy(config.Mqtt_RootCaCert, root["mqtt_root_ca_cert"].as<String>().c_str(), sizeof(config.Mqtt_RootCaCert));
|
||||
config.Mqtt_Port = root["mqtt_port"].as<uint>();
|
||||
strlcpy(config.Mqtt_Hostname, root["mqtt_hostname"].as<String>().c_str(), sizeof(config.Mqtt_Hostname));
|
||||
strlcpy(config.Mqtt_Username, root["mqtt_username"].as<String>().c_str(), sizeof(config.Mqtt_Username));
|
||||
strlcpy(config.Mqtt_Password, root["mqtt_password"].as<String>().c_str(), sizeof(config.Mqtt_Password));
|
||||
strlcpy(config.Mqtt_Topic, root["mqtt_topic"].as<String>().c_str(), sizeof(config.Mqtt_Topic));
|
||||
strlcpy(config.Mqtt_LwtTopic, root["mqtt_lwt_topic"].as<String>().c_str(), sizeof(config.Mqtt_LwtTopic));
|
||||
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_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>();
|
||||
config.Mqtt_Hass_IndividualPanels = root["mqtt_hass_individualpanels"].as<bool>();
|
||||
strlcpy(config.Mqtt_Hass_Topic, root["mqtt_hass_topic"].as<String>().c_str(), sizeof(config.Mqtt_Hass_Topic));
|
||||
Configuration.write();
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Settings saved!");
|
||||
retMsg[F("code")] = WebApiError::GenericSuccess;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Settings saved!";
|
||||
retMsg["code"] = WebApiError::GenericSuccess;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
@ -34,22 +34,22 @@ void WebApiNetworkClass::onNetworkStatus(AsyncWebServerRequest* request)
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
root[F("sta_status")] = ((WiFi.getMode() & WIFI_STA) != 0);
|
||||
root[F("sta_ssid")] = WiFi.SSID();
|
||||
root[F("sta_rssi")] = WiFi.RSSI();
|
||||
root[F("network_hostname")] = NetworkSettings.getHostname();
|
||||
root[F("network_ip")] = NetworkSettings.localIP().toString();
|
||||
root[F("network_netmask")] = NetworkSettings.subnetMask().toString();
|
||||
root[F("network_gateway")] = NetworkSettings.gatewayIP().toString();
|
||||
root[F("network_dns1")] = NetworkSettings.dnsIP(0).toString();
|
||||
root[F("network_dns2")] = NetworkSettings.dnsIP(1).toString();
|
||||
root[F("network_mac")] = NetworkSettings.macAddress();
|
||||
root[F("network_mode")] = NetworkSettings.NetworkMode() == network_mode::WiFi ? F("Station") : F("Ethernet");
|
||||
root[F("ap_status")] = ((WiFi.getMode() & WIFI_AP) != 0);
|
||||
root[F("ap_ssid")] = NetworkSettings.getApName();
|
||||
root[F("ap_ip")] = WiFi.softAPIP().toString();
|
||||
root[F("ap_mac")] = WiFi.softAPmacAddress();
|
||||
root[F("ap_stationnum")] = WiFi.softAPgetStationNum();
|
||||
root["sta_status"] = ((WiFi.getMode() & WIFI_STA) != 0);
|
||||
root["sta_ssid"] = WiFi.SSID();
|
||||
root["sta_rssi"] = WiFi.RSSI();
|
||||
root["network_hostname"] = NetworkSettings.getHostname();
|
||||
root["network_ip"] = NetworkSettings.localIP().toString();
|
||||
root["network_netmask"] = NetworkSettings.subnetMask().toString();
|
||||
root["network_gateway"] = NetworkSettings.gatewayIP().toString();
|
||||
root["network_dns1"] = NetworkSettings.dnsIP(0).toString();
|
||||
root["network_dns2"] = NetworkSettings.dnsIP(1).toString();
|
||||
root["network_mac"] = NetworkSettings.macAddress();
|
||||
root["network_mode"] = NetworkSettings.NetworkMode() == network_mode::WiFi ? "Station" : "Ethernet";
|
||||
root["ap_status"] = ((WiFi.getMode() & WIFI_AP) != 0);
|
||||
root["ap_ssid"] = NetworkSettings.getApName();
|
||||
root["ap_ip"] = WiFi.softAPIP().toString();
|
||||
root["ap_mac"] = WiFi.softAPmacAddress();
|
||||
root["ap_stationnum"] = WiFi.softAPgetStationNum();
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -65,15 +65,15 @@ void WebApiNetworkClass::onNetworkAdminGet(AsyncWebServerRequest* request)
|
||||
JsonObject root = response->getRoot();
|
||||
const CONFIG_T& config = Configuration.get();
|
||||
|
||||
root[F("hostname")] = config.WiFi_Hostname;
|
||||
root[F("dhcp")] = config.WiFi_Dhcp;
|
||||
root[F("ipaddress")] = IPAddress(config.WiFi_Ip).toString();
|
||||
root[F("netmask")] = IPAddress(config.WiFi_Netmask).toString();
|
||||
root[F("gateway")] = IPAddress(config.WiFi_Gateway).toString();
|
||||
root[F("dns1")] = IPAddress(config.WiFi_Dns1).toString();
|
||||
root[F("dns2")] = IPAddress(config.WiFi_Dns2).toString();
|
||||
root[F("ssid")] = config.WiFi_Ssid;
|
||||
root[F("password")] = config.WiFi_Password;
|
||||
root["hostname"] = config.WiFi_Hostname;
|
||||
root["dhcp"] = config.WiFi_Dhcp;
|
||||
root["ipaddress"] = IPAddress(config.WiFi_Ip).toString();
|
||||
root["netmask"] = IPAddress(config.WiFi_Netmask).toString();
|
||||
root["gateway"] = IPAddress(config.WiFi_Gateway).toString();
|
||||
root["dns1"] = IPAddress(config.WiFi_Dns1).toString();
|
||||
root["dns2"] = IPAddress(config.WiFi_Dns2).toString();
|
||||
root["ssid"] = config.WiFi_Ssid;
|
||||
root["password"] = config.WiFi_Password;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -87,11 +87,11 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -100,8 +100,8 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -111,78 +111,78 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(root.containsKey("ssid") && root.containsKey("password") && root.containsKey("hostname") && root.containsKey("dhcp") && root.containsKey("ipaddress") && root.containsKey("netmask") && root.containsKey("gateway") && root.containsKey("dns1") && root.containsKey("dns2"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
IPAddress ipaddress;
|
||||
if (!ipaddress.fromString(root[F("ipaddress")].as<String>())) {
|
||||
retMsg[F("message")] = F("IP address is invalid!");
|
||||
retMsg[F("code")] = WebApiError::NetworkIpInvalid;
|
||||
if (!ipaddress.fromString(root["ipaddress"].as<String>())) {
|
||||
retMsg["message"] = "IP address is invalid!";
|
||||
retMsg["code"] = WebApiError::NetworkIpInvalid;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
IPAddress netmask;
|
||||
if (!netmask.fromString(root[F("netmask")].as<String>())) {
|
||||
retMsg[F("message")] = F("Netmask is invalid!");
|
||||
retMsg[F("code")] = WebApiError::NetworkNetmaskInvalid;
|
||||
if (!netmask.fromString(root["netmask"].as<String>())) {
|
||||
retMsg["message"] = "Netmask is invalid!";
|
||||
retMsg["code"] = WebApiError::NetworkNetmaskInvalid;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
IPAddress gateway;
|
||||
if (!gateway.fromString(root[F("gateway")].as<String>())) {
|
||||
retMsg[F("message")] = F("Gateway is invalid!");
|
||||
retMsg[F("code")] = WebApiError::NetworkGatewayInvalid;
|
||||
if (!gateway.fromString(root["gateway"].as<String>())) {
|
||||
retMsg["message"] = "Gateway is invalid!";
|
||||
retMsg["code"] = WebApiError::NetworkGatewayInvalid;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
IPAddress dns1;
|
||||
if (!dns1.fromString(root[F("dns1")].as<String>())) {
|
||||
retMsg[F("message")] = F("DNS Server IP 1 is invalid!");
|
||||
retMsg[F("code")] = WebApiError::NetworkDns1Invalid;
|
||||
if (!dns1.fromString(root["dns1"].as<String>())) {
|
||||
retMsg["message"] = "DNS Server IP 1 is invalid!";
|
||||
retMsg["code"] = WebApiError::NetworkDns1Invalid;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
IPAddress dns2;
|
||||
if (!dns2.fromString(root[F("dns2")].as<String>())) {
|
||||
retMsg[F("message")] = F("DNS Server IP 2 is invalid!");
|
||||
retMsg[F("code")] = WebApiError::NetworkDns2Invalid;
|
||||
if (!dns2.fromString(root["dns2"].as<String>())) {
|
||||
retMsg["message"] = "DNS Server IP 2 is invalid!";
|
||||
retMsg["code"] = WebApiError::NetworkDns2Invalid;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("hostname")].as<String>().length() == 0 || root[F("hostname")].as<String>().length() > WIFI_MAX_HOSTNAME_STRLEN) {
|
||||
retMsg[F("message")] = F("Hostname must between 1 and " STR(WIFI_MAX_HOSTNAME_STRLEN) " characters long!");
|
||||
if (root["hostname"].as<String>().length() == 0 || root["hostname"].as<String>().length() > WIFI_MAX_HOSTNAME_STRLEN) {
|
||||
retMsg["message"] = "Hostname must between 1 and " STR(WIFI_MAX_HOSTNAME_STRLEN) " characters long!";
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
if (NetworkSettings.NetworkMode() == network_mode::WiFi) {
|
||||
if (root[F("ssid")].as<String>().length() == 0 || root[F("ssid")].as<String>().length() > WIFI_MAX_SSID_STRLEN) {
|
||||
retMsg[F("message")] = F("SSID must between 1 and " STR(WIFI_MAX_SSID_STRLEN) " characters long!");
|
||||
if (root["ssid"].as<String>().length() == 0 || root["ssid"].as<String>().length() > WIFI_MAX_SSID_STRLEN) {
|
||||
retMsg["message"] = "SSID must between 1 and " STR(WIFI_MAX_SSID_STRLEN) " characters long!";
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (root[F("password")].as<String>().length() > WIFI_MAX_PASSWORD_STRLEN - 1) {
|
||||
retMsg[F("message")] = F("Password must not be longer than " STR(WIFI_MAX_PASSWORD_STRLEN) " characters long!");
|
||||
if (root["password"].as<String>().length() > WIFI_MAX_PASSWORD_STRLEN - 1) {
|
||||
retMsg["message"] = "Password must not be longer than " STR(WIFI_MAX_PASSWORD_STRLEN) " characters long!";
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -209,19 +209,19 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
|
||||
config.WiFi_Dns2[1] = dns2[1];
|
||||
config.WiFi_Dns2[2] = dns2[2];
|
||||
config.WiFi_Dns2[3] = dns2[3];
|
||||
strlcpy(config.WiFi_Ssid, root[F("ssid")].as<String>().c_str(), sizeof(config.WiFi_Ssid));
|
||||
strlcpy(config.WiFi_Password, root[F("password")].as<String>().c_str(), sizeof(config.WiFi_Password));
|
||||
strlcpy(config.WiFi_Hostname, root[F("hostname")].as<String>().c_str(), sizeof(config.WiFi_Hostname));
|
||||
if (root[F("dhcp")].as<bool>()) {
|
||||
strlcpy(config.WiFi_Ssid, root["ssid"].as<String>().c_str(), sizeof(config.WiFi_Ssid));
|
||||
strlcpy(config.WiFi_Password, root["password"].as<String>().c_str(), sizeof(config.WiFi_Password));
|
||||
strlcpy(config.WiFi_Hostname, root["hostname"].as<String>().c_str(), sizeof(config.WiFi_Hostname));
|
||||
if (root["dhcp"].as<bool>()) {
|
||||
config.WiFi_Dhcp = true;
|
||||
} else {
|
||||
config.WiFi_Dhcp = false;
|
||||
}
|
||||
Configuration.write();
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Settings saved!");
|
||||
retMsg[F("code")] = WebApiError::GenericSuccess;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Settings saved!";
|
||||
retMsg["code"] = WebApiError::GenericSuccess;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
@ -38,29 +38,29 @@ void WebApiNtpClass::onNtpStatus(AsyncWebServerRequest* request)
|
||||
JsonObject root = response->getRoot();
|
||||
const CONFIG_T& config = Configuration.get();
|
||||
|
||||
root[F("ntp_server")] = config.Ntp_Server;
|
||||
root[F("ntp_timezone")] = config.Ntp_Timezone;
|
||||
root[F("ntp_timezone_descr")] = config.Ntp_TimezoneDescr;
|
||||
root["ntp_server"] = config.Ntp_Server;
|
||||
root["ntp_timezone"] = config.Ntp_Timezone;
|
||||
root["ntp_timezone_descr"] = config.Ntp_TimezoneDescr;
|
||||
|
||||
struct tm timeinfo;
|
||||
if (!getLocalTime(&timeinfo, 5)) {
|
||||
root[F("ntp_status")] = false;
|
||||
root["ntp_status"] = false;
|
||||
} else {
|
||||
root[F("ntp_status")] = true;
|
||||
root["ntp_status"] = true;
|
||||
}
|
||||
char timeStringBuff[50];
|
||||
strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo);
|
||||
root[F("ntp_localtime")] = timeStringBuff;
|
||||
root["ntp_localtime"] = timeStringBuff;
|
||||
|
||||
SunPosition.sunriseTime(&timeinfo);
|
||||
strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo);
|
||||
root[F("sun_risetime")] = timeStringBuff;
|
||||
root["sun_risetime"] = timeStringBuff;
|
||||
|
||||
SunPosition.sunsetTime(&timeinfo);
|
||||
strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo);
|
||||
root[F("sun_settime")] = timeStringBuff;
|
||||
root["sun_settime"] = timeStringBuff;
|
||||
|
||||
root[F("sun_isDayPeriod")] = SunPosition.isDayPeriod();
|
||||
root["sun_isDayPeriod"] = SunPosition.isDayPeriod();
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -76,11 +76,11 @@ void WebApiNtpClass::onNtpAdminGet(AsyncWebServerRequest* request)
|
||||
JsonObject root = response->getRoot();
|
||||
const CONFIG_T& config = Configuration.get();
|
||||
|
||||
root[F("ntp_server")] = config.Ntp_Server;
|
||||
root[F("ntp_timezone")] = config.Ntp_Timezone;
|
||||
root[F("ntp_timezone_descr")] = config.Ntp_TimezoneDescr;
|
||||
root[F("longitude")] = config.Ntp_Longitude;
|
||||
root[F("latitude")] = config.Ntp_Latitude;
|
||||
root["ntp_server"] = config.Ntp_Server;
|
||||
root["ntp_timezone"] = config.Ntp_Timezone;
|
||||
root["ntp_timezone_descr"] = config.Ntp_TimezoneDescr;
|
||||
root["longitude"] = config.Ntp_Longitude;
|
||||
root["latitude"] = config.Ntp_Latitude;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -94,11 +94,11 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -107,8 +107,8 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -118,59 +118,59 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(root.containsKey("ntp_server") && root.containsKey("ntp_timezone") && root.containsKey("longitude") && root.containsKey("latitude"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("ntp_server")].as<String>().length() == 0 || root[F("ntp_server")].as<String>().length() > NTP_MAX_SERVER_STRLEN) {
|
||||
retMsg[F("message")] = F("NTP Server must between 1 and " STR(NTP_MAX_SERVER_STRLEN) " characters long!");
|
||||
retMsg[F("code")] = WebApiError::NtpServerLength;
|
||||
retMsg[F("param")][F("max")] = NTP_MAX_SERVER_STRLEN;
|
||||
if (root["ntp_server"].as<String>().length() == 0 || root["ntp_server"].as<String>().length() > NTP_MAX_SERVER_STRLEN) {
|
||||
retMsg["message"] = "NTP Server must between 1 and " STR(NTP_MAX_SERVER_STRLEN) " characters long!";
|
||||
retMsg["code"] = WebApiError::NtpServerLength;
|
||||
retMsg["param"]["max"] = NTP_MAX_SERVER_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("ntp_timezone")].as<String>().length() == 0 || root[F("ntp_timezone")].as<String>().length() > NTP_MAX_TIMEZONE_STRLEN) {
|
||||
retMsg[F("message")] = F("Timezone must between 1 and " STR(NTP_MAX_TIMEZONE_STRLEN) " characters long!");
|
||||
retMsg[F("code")] = WebApiError::NtpTimezoneLength;
|
||||
retMsg[F("param")][F("max")] = NTP_MAX_TIMEZONE_STRLEN;
|
||||
if (root["ntp_timezone"].as<String>().length() == 0 || root["ntp_timezone"].as<String>().length() > NTP_MAX_TIMEZONE_STRLEN) {
|
||||
retMsg["message"] = "Timezone must between 1 and " STR(NTP_MAX_TIMEZONE_STRLEN) " characters long!";
|
||||
retMsg["code"] = WebApiError::NtpTimezoneLength;
|
||||
retMsg["param"]["max"] = NTP_MAX_TIMEZONE_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("ntp_timezone_descr")].as<String>().length() == 0 || root[F("ntp_timezone_descr")].as<String>().length() > NTP_MAX_TIMEZONEDESCR_STRLEN) {
|
||||
retMsg[F("message")] = F("Timezone description must between 1 and " STR(NTP_MAX_TIMEZONEDESCR_STRLEN) " characters long!");
|
||||
retMsg[F("code")] = WebApiError::NtpTimezoneDescriptionLength;
|
||||
retMsg[F("param")][F("max")] = NTP_MAX_TIMEZONEDESCR_STRLEN;
|
||||
if (root["ntp_timezone_descr"].as<String>().length() == 0 || root["ntp_timezone_descr"].as<String>().length() > NTP_MAX_TIMEZONEDESCR_STRLEN) {
|
||||
retMsg["message"] = "Timezone description must between 1 and " STR(NTP_MAX_TIMEZONEDESCR_STRLEN) " characters long!";
|
||||
retMsg["code"] = WebApiError::NtpTimezoneDescriptionLength;
|
||||
retMsg["param"]["max"] = NTP_MAX_TIMEZONEDESCR_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
CONFIG_T& config = Configuration.get();
|
||||
strlcpy(config.Ntp_Server, root[F("ntp_server")].as<String>().c_str(), sizeof(config.Ntp_Server));
|
||||
strlcpy(config.Ntp_Timezone, root[F("ntp_timezone")].as<String>().c_str(), sizeof(config.Ntp_Timezone));
|
||||
strlcpy(config.Ntp_TimezoneDescr, root[F("ntp_timezone_descr")].as<String>().c_str(), sizeof(config.Ntp_TimezoneDescr));
|
||||
config.Ntp_Latitude = root[F("latitude")].as<double>();
|
||||
config.Ntp_Longitude = root[F("longitude")].as<double>();
|
||||
strlcpy(config.Ntp_Server, root["ntp_server"].as<String>().c_str(), sizeof(config.Ntp_Server));
|
||||
strlcpy(config.Ntp_Timezone, root["ntp_timezone"].as<String>().c_str(), sizeof(config.Ntp_Timezone));
|
||||
strlcpy(config.Ntp_TimezoneDescr, root["ntp_timezone_descr"].as<String>().c_str(), sizeof(config.Ntp_TimezoneDescr));
|
||||
config.Ntp_Latitude = root["latitude"].as<double>();
|
||||
config.Ntp_Longitude = root["longitude"].as<double>();
|
||||
Configuration.write();
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Settings saved!");
|
||||
retMsg[F("code")] = WebApiError::GenericSuccess;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Settings saved!";
|
||||
retMsg["code"] = WebApiError::GenericSuccess;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -190,17 +190,17 @@ void WebApiNtpClass::onNtpTimeGet(AsyncWebServerRequest* request)
|
||||
|
||||
struct tm timeinfo;
|
||||
if (!getLocalTime(&timeinfo, 5)) {
|
||||
root[F("ntp_status")] = false;
|
||||
root["ntp_status"] = false;
|
||||
} else {
|
||||
root[F("ntp_status")] = true;
|
||||
root["ntp_status"] = true;
|
||||
}
|
||||
|
||||
root[F("year")] = timeinfo.tm_year + 1900;
|
||||
root[F("month")] = timeinfo.tm_mon + 1;
|
||||
root[F("day")] = timeinfo.tm_mday;
|
||||
root[F("hour")] = timeinfo.tm_hour;
|
||||
root[F("minute")] = timeinfo.tm_min;
|
||||
root[F("second")] = timeinfo.tm_sec;
|
||||
root["year"] = timeinfo.tm_year + 1900;
|
||||
root["month"] = timeinfo.tm_mon + 1;
|
||||
root["day"] = timeinfo.tm_mday;
|
||||
root["hour"] = timeinfo.tm_hour;
|
||||
root["minute"] = timeinfo.tm_min;
|
||||
root["second"] = timeinfo.tm_sec;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -214,11 +214,11 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -227,8 +227,8 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -238,8 +238,8 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -251,89 +251,89 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
|
||||
&& root.containsKey("hour")
|
||||
&& root.containsKey("minute")
|
||||
&& root.containsKey("second"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("year")].as<uint>() < 2022 || root[F("year")].as<uint>() > 2100) {
|
||||
retMsg[F("message")] = F("Year must be a number between 2022 and 2100!");
|
||||
retMsg[F("code")] = WebApiError::NtpYearInvalid;
|
||||
retMsg[F("param")][F("min")] = 2022;
|
||||
retMsg[F("param")][F("max")] = 2100;
|
||||
if (root["year"].as<uint>() < 2022 || root["year"].as<uint>() > 2100) {
|
||||
retMsg["message"] = "Year must be a number between 2022 and 2100!";
|
||||
retMsg["code"] = WebApiError::NtpYearInvalid;
|
||||
retMsg["param"]["min"] = 2022;
|
||||
retMsg["param"]["max"] = 2100;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("month")].as<uint>() < 1 || root[F("month")].as<uint>() > 12) {
|
||||
retMsg[F("message")] = F("Month must be a number between 1 and 12!");
|
||||
retMsg[F("code")] = WebApiError::NtpMonthInvalid;
|
||||
retMsg[F("param")][F("min")] = 1;
|
||||
retMsg[F("param")][F("max")] = 12;
|
||||
if (root["month"].as<uint>() < 1 || root["month"].as<uint>() > 12) {
|
||||
retMsg["message"] = "Month must be a number between 1 and 12!";
|
||||
retMsg["code"] = WebApiError::NtpMonthInvalid;
|
||||
retMsg["param"]["min"] = 1;
|
||||
retMsg["param"]["max"] = 12;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("day")].as<uint>() < 1 || root[F("day")].as<uint>() > 31) {
|
||||
retMsg[F("message")] = F("Day must be a number between 1 and 31!");
|
||||
retMsg[F("code")] = WebApiError::NtpDayInvalid;
|
||||
retMsg[F("param")][F("min")] = 1;
|
||||
retMsg[F("param")][F("max")] = 31;
|
||||
if (root["day"].as<uint>() < 1 || root["day"].as<uint>() > 31) {
|
||||
retMsg["message"] = "Day must be a number between 1 and 31!";
|
||||
retMsg["code"] = WebApiError::NtpDayInvalid;
|
||||
retMsg["param"]["min"] = 1;
|
||||
retMsg["param"]["max"] = 31;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("hour")].as<uint>() > 23) {
|
||||
retMsg[F("message")] = F("Hour must be a number between 0 and 23!");
|
||||
retMsg[F("code")] = WebApiError::NtpHourInvalid;
|
||||
retMsg[F("param")][F("min")] = 0;
|
||||
retMsg[F("param")][F("max")] = 23;
|
||||
if (root["hour"].as<uint>() > 23) {
|
||||
retMsg["message"] = "Hour must be a number between 0 and 23!";
|
||||
retMsg["code"] = WebApiError::NtpHourInvalid;
|
||||
retMsg["param"]["min"] = 0;
|
||||
retMsg["param"]["max"] = 23;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("minute")].as<uint>() > 59) {
|
||||
retMsg[F("message")] = F("Minute must be a number between 0 and 59!");
|
||||
retMsg[F("code")] = WebApiError::NtpMinuteInvalid;
|
||||
retMsg[F("param")][F("min")] = 0;
|
||||
retMsg[F("param")][F("max")] = 59;
|
||||
if (root["minute"].as<uint>() > 59) {
|
||||
retMsg["message"] = "Minute must be a number between 0 and 59!";
|
||||
retMsg["code"] = WebApiError::NtpMinuteInvalid;
|
||||
retMsg["param"]["min"] = 0;
|
||||
retMsg["param"]["max"] = 59;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("second")].as<uint>() > 59) {
|
||||
retMsg[F("message")] = F("Second must be a number between 0 and 59!");
|
||||
retMsg[F("code")] = WebApiError::NtpSecondInvalid;
|
||||
retMsg[F("param")][F("min")] = 0;
|
||||
retMsg[F("param")][F("max")] = 59;
|
||||
if (root["second"].as<uint>() > 59) {
|
||||
retMsg["message"] = "Second must be a number between 0 and 59!";
|
||||
retMsg["code"] = WebApiError::NtpSecondInvalid;
|
||||
retMsg["param"]["min"] = 0;
|
||||
retMsg["param"]["max"] = 59;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
tm local;
|
||||
local.tm_sec = root[F("second")].as<uint>(); // seconds after the minute - [ 0 to 59 ]
|
||||
local.tm_min = root[F("minute")].as<uint>(); // minutes after the hour - [ 0 to 59 ]
|
||||
local.tm_hour = root[F("hour")].as<uint>(); // hours since midnight - [ 0 to 23 ]
|
||||
local.tm_mday = root[F("day")].as<uint>(); // day of the month - [ 1 to 31 ]
|
||||
local.tm_mon = root[F("month")].as<uint>() - 1; // months since January - [ 0 to 11 ]
|
||||
local.tm_year = root[F("year")].as<uint>() - 1900; // years since 1900
|
||||
local.tm_sec = root["second"].as<uint>(); // seconds after the minute - [ 0 to 59 ]
|
||||
local.tm_min = root["minute"].as<uint>(); // minutes after the hour - [ 0 to 59 ]
|
||||
local.tm_hour = root["hour"].as<uint>(); // hours since midnight - [ 0 to 23 ]
|
||||
local.tm_mday = root["day"].as<uint>(); // day of the month - [ 1 to 31 ]
|
||||
local.tm_mon = root["month"].as<uint>() - 1; // months since January - [ 0 to 11 ]
|
||||
local.tm_year = root["year"].as<uint>() - 1900; // years since 1900
|
||||
local.tm_isdst = -1;
|
||||
|
||||
time_t t = mktime(&local);
|
||||
struct timeval now = { .tv_sec = t, .tv_usec = 0 };
|
||||
settimeofday(&now, NULL);
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Time updated!");
|
||||
retMsg[F("code")] = WebApiError::NtpTimeUpdated;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Time updated!";
|
||||
retMsg["code"] = WebApiError::NtpTimeUpdated;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
@ -58,11 +58,11 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -71,8 +71,8 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -82,8 +82,8 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -91,43 +91,43 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
|
||||
|
||||
if (!(root.containsKey("serial")
|
||||
&& (root.containsKey("power") || root.containsKey("restart")))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("serial")].as<uint64_t>() == 0) {
|
||||
retMsg[F("message")] = F("Serial must be a number > 0!");
|
||||
retMsg[F("code")] = WebApiError::PowerSerialZero;
|
||||
if (root["serial"].as<uint64_t>() == 0) {
|
||||
retMsg["message"] = "Serial must be a number > 0!";
|
||||
retMsg["code"] = WebApiError::PowerSerialZero;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t serial = strtoll(root[F("serial")].as<String>().c_str(), NULL, 16);
|
||||
uint64_t serial = strtoll(root["serial"].as<String>().c_str(), NULL, 16);
|
||||
auto inv = Hoymiles.getInverterBySerial(serial);
|
||||
if (inv == nullptr) {
|
||||
retMsg[F("message")] = F("Invalid inverter specified!");
|
||||
retMsg[F("code")] = WebApiError::PowerInvalidInverter;
|
||||
retMsg["message"] = "Invalid inverter specified!";
|
||||
retMsg["code"] = WebApiError::PowerInvalidInverter;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root.containsKey("power")) {
|
||||
uint16_t power = root[F("power")].as<bool>();
|
||||
uint16_t power = root["power"].as<bool>();
|
||||
inv->sendPowerControlRequest(Hoymiles.getRadio(), power);
|
||||
} else {
|
||||
if (root[F("restart")].as<bool>()) {
|
||||
if (root["restart"].as<bool>()) {
|
||||
inv->sendRestartControlRequest(Hoymiles.getRadio());
|
||||
}
|
||||
}
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Settings saved!");
|
||||
retMsg[F("code")] = WebApiError::GenericSuccess;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Settings saved!";
|
||||
retMsg["code"] = WebApiError::GenericSuccess;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
@ -28,29 +28,29 @@ void WebApiPrometheusClass::onPrometheusMetricsGet(AsyncWebServerRequest* reques
|
||||
try {
|
||||
auto stream = request->beginResponseStream("text/plain; charset=utf-8", 40960);
|
||||
|
||||
stream->print(F("# HELP opendtu_build Build info\n"));
|
||||
stream->print(F("# TYPE opendtu_build gauge\n"));
|
||||
stream->print("# HELP opendtu_build Build info\n");
|
||||
stream->print("# TYPE opendtu_build gauge\n");
|
||||
stream->printf("opendtu_build{name=\"%s\",id=\"%s\",version=\"%d.%d.%d\"} 1\n",
|
||||
NetworkSettings.getHostname().c_str(), AUTO_GIT_HASH, CONFIG_VERSION >> 24 & 0xff, CONFIG_VERSION >> 16 & 0xff, CONFIG_VERSION >> 8 & 0xff);
|
||||
|
||||
stream->print(F("# HELP opendtu_platform Platform info\n"));
|
||||
stream->print(F("# TYPE opendtu_platform gauge\n"));
|
||||
stream->print("# HELP opendtu_platform Platform info\n");
|
||||
stream->print("# TYPE opendtu_platform gauge\n");
|
||||
stream->printf("opendtu_platform{arch=\"%s\",mac=\"%s\"} 1\n", ESP.getChipModel(), NetworkSettings.macAddress().c_str());
|
||||
|
||||
stream->print(F("# HELP opendtu_uptime Uptime in seconds\n"));
|
||||
stream->print(F("# TYPE opendtu_uptime counter\n"));
|
||||
stream->print("# HELP opendtu_uptime Uptime in seconds\n");
|
||||
stream->print("# TYPE opendtu_uptime counter\n");
|
||||
stream->printf("opendtu_uptime %lld\n", esp_timer_get_time() / 1000000);
|
||||
|
||||
stream->print(F("# HELP opendtu_heap_size System memory size\n"));
|
||||
stream->print(F("# TYPE opendtu_heap_size gauge\n"));
|
||||
stream->print("# HELP opendtu_heap_size System memory size\n");
|
||||
stream->print("# TYPE opendtu_heap_size gauge\n");
|
||||
stream->printf("opendtu_heap_size %zu\n", ESP.getHeapSize());
|
||||
|
||||
stream->print(F("# HELP opendtu_free_heap_size System free memory\n"));
|
||||
stream->print(F("# TYPE opendtu_free_heap_size gauge\n"));
|
||||
stream->print("# HELP opendtu_free_heap_size System free memory\n");
|
||||
stream->print("# TYPE opendtu_free_heap_size gauge\n");
|
||||
stream->printf("opendtu_free_heap_size %zu\n", ESP.getFreeHeap());
|
||||
|
||||
stream->print(F("# HELP wifi_rssi WiFi RSSI\n"));
|
||||
stream->print(F("# TYPE wifi_rssi gauge\n"));
|
||||
stream->print("# HELP wifi_rssi WiFi RSSI\n");
|
||||
stream->print("# TYPE wifi_rssi gauge\n");
|
||||
stream->printf("wifi_rssi %d\n", WiFi.RSSI());
|
||||
|
||||
for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) {
|
||||
@ -59,8 +59,8 @@ void WebApiPrometheusClass::onPrometheusMetricsGet(AsyncWebServerRequest* reques
|
||||
String serial = inv->serialString();
|
||||
const char* name = inv->name();
|
||||
if (i == 0) {
|
||||
stream->print(F("# HELP opendtu_last_update last update from inverter in s\n"));
|
||||
stream->print(F("# TYPE opendtu_last_update gauge\n"));
|
||||
stream->print("# HELP opendtu_last_update last update from inverter in s\n");
|
||||
stream->print("# TYPE opendtu_last_update gauge\n");
|
||||
}
|
||||
stream->printf("opendtu_last_update{serial=\"%s\",unit=\"%d\",name=\"%s\"} %d\n",
|
||||
serial.c_str(), i, name, inv->Statistics()->getLastUpdate() / 1000);
|
||||
@ -92,7 +92,7 @@ void WebApiPrometheusClass::onPrometheusMetricsGet(AsyncWebServerRequest* reques
|
||||
}
|
||||
}
|
||||
}
|
||||
stream->addHeader(F("Cache-Control"), F("no-cache"));
|
||||
stream->addHeader("Cache-Control", "no-cache");
|
||||
request->send(stream);
|
||||
|
||||
} catch (std::bad_alloc& bad_alloc) {
|
||||
@ -131,8 +131,8 @@ void WebApiPrometheusClass::addPanelInfo(AsyncResponseStream* stream, String& se
|
||||
|
||||
const bool printHelp = (idx == 0 && channel == 0);
|
||||
if (printHelp) {
|
||||
stream->print(F("# HELP opendtu_PanelInfo panel information\n"));
|
||||
stream->print(F("# TYPE opendtu_PanelInfo gauge\n"));
|
||||
stream->print("# HELP opendtu_PanelInfo panel information\n");
|
||||
stream->print("# TYPE opendtu_PanelInfo gauge\n");
|
||||
}
|
||||
stream->printf("opendtu_PanelInfo{serial=\"%s\",unit=\"%d\",name=\"%s\",channel=\"%d\",panelname=\"%s\"} 1\n",
|
||||
serial.c_str(),
|
||||
@ -143,8 +143,8 @@ void WebApiPrometheusClass::addPanelInfo(AsyncResponseStream* stream, String& se
|
||||
);
|
||||
|
||||
if (printHelp) {
|
||||
stream->print(F("# HELP opendtu_MaxPower panel maximum output power\n"));
|
||||
stream->print(F("# TYPE opendtu_MaxPower gauge\n"));
|
||||
stream->print("# HELP opendtu_MaxPower panel maximum output power\n");
|
||||
stream->print("# TYPE opendtu_MaxPower gauge\n");
|
||||
}
|
||||
stream->printf("opendtu_MaxPower{serial=\"%s\",unit=\"%d\",name=\"%s\",channel=\"%d\"} %d\n",
|
||||
serial.c_str(),
|
||||
@ -155,8 +155,8 @@ void WebApiPrometheusClass::addPanelInfo(AsyncResponseStream* stream, String& se
|
||||
);
|
||||
|
||||
if (printHelp) {
|
||||
stream->print(F("# HELP opendtu_YieldTotalOffset panel yield offset (for used inverters)\n"));
|
||||
stream->print(F("# TYPE opendtu_YieldTotalOffset gauge\n"));
|
||||
stream->print("# HELP opendtu_YieldTotalOffset panel yield offset (for used inverters)\n");
|
||||
stream->print("# TYPE opendtu_YieldTotalOffset gauge\n");
|
||||
}
|
||||
stream->printf("opendtu_YieldTotalOffset{serial=\"%s\",unit=\"%d\",name=\"%s\",channel=\"%d\"} %f\n",
|
||||
serial.c_str(),
|
||||
|
||||
@ -34,8 +34,8 @@ void WebApiSecurityClass::onSecurityGet(AsyncWebServerRequest* request)
|
||||
JsonObject root = response->getRoot();
|
||||
const CONFIG_T& config = Configuration.get();
|
||||
|
||||
root[F("password")] = config.Security_Password;
|
||||
root[F("allow_readonly")] = config.Security_AllowReadonly;
|
||||
root["password"] = config.Security_Password;
|
||||
root["allow_readonly"] = config.Security_AllowReadonly;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -49,11 +49,11 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
retMsg["type"] = "warning";
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
retMsg["message"] = "No values found!";
|
||||
retMsg["code"] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -62,8 +62,8 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
retMsg["message"] = "Data too large!";
|
||||
retMsg["code"] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -73,8 +73,8 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
retMsg["message"] = "Failed to parse data!";
|
||||
retMsg["code"] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
@ -82,30 +82,30 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
|
||||
|
||||
if (!root.containsKey("password")
|
||||
&& root.containsKey("allow_readonly")) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
retMsg["message"] = "Values are missing!";
|
||||
retMsg["code"] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("password")].as<String>().length() < 8 || root[F("password")].as<String>().length() > WIFI_MAX_PASSWORD_STRLEN) {
|
||||
retMsg[F("message")] = F("Password must between 8 and " STR(WIFI_MAX_PASSWORD_STRLEN) " characters long!");
|
||||
retMsg[F("code")] = WebApiError::SecurityPasswordLength;
|
||||
retMsg[F("param")][F("max")] = WIFI_MAX_PASSWORD_STRLEN;
|
||||
if (root["password"].as<String>().length() < 8 || root["password"].as<String>().length() > WIFI_MAX_PASSWORD_STRLEN) {
|
||||
retMsg["message"] = "Password must between 8 and " STR(WIFI_MAX_PASSWORD_STRLEN) " characters long!";
|
||||
retMsg["code"] = WebApiError::SecurityPasswordLength;
|
||||
retMsg["param"]["max"] = WIFI_MAX_PASSWORD_STRLEN;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
CONFIG_T& config = Configuration.get();
|
||||
strlcpy(config.Security_Password, root[F("password")].as<String>().c_str(), sizeof(config.Security_Password));
|
||||
config.Security_AllowReadonly = root[F("allow_readonly")].as<bool>();
|
||||
strlcpy(config.Security_Password, root["password"].as<String>().c_str(), sizeof(config.Security_Password));
|
||||
config.Security_AllowReadonly = root["allow_readonly"].as<bool>();
|
||||
Configuration.write();
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Settings saved!");
|
||||
retMsg[F("code")] = WebApiError::GenericSuccess;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Settings saved!";
|
||||
retMsg["code"] = WebApiError::GenericSuccess;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -119,9 +119,9 @@ void WebApiSecurityClass::onAuthenticateGet(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Authentication successful!");
|
||||
retMsg[F("code")] = WebApiError::SecurityAuthSuccess;
|
||||
retMsg["type"] = "success";
|
||||
retMsg["message"] = "Authentication successful!";
|
||||
retMsg["code"] = WebApiError::SecurityAuthSuccess;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
@ -37,40 +37,40 @@ void WebApiSysstatusClass::onSystemStatus(AsyncWebServerRequest* request)
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
root[F("hostname")] = NetworkSettings.getHostname();
|
||||
root["hostname"] = NetworkSettings.getHostname();
|
||||
|
||||
root[F("sdkversion")] = ESP.getSdkVersion();
|
||||
root[F("cpufreq")] = ESP.getCpuFreqMHz();
|
||||
root["sdkversion"] = ESP.getSdkVersion();
|
||||
root["cpufreq"] = ESP.getCpuFreqMHz();
|
||||
|
||||
root[F("heap_total")] = ESP.getHeapSize();
|
||||
root[F("heap_used")] = ESP.getHeapSize() - ESP.getFreeHeap();
|
||||
root[F("sketch_total")] = ESP.getFreeSketchSpace();
|
||||
root[F("sketch_used")] = ESP.getSketchSize();
|
||||
root[F("littlefs_total")] = LittleFS.totalBytes();
|
||||
root[F("littlefs_used")] = LittleFS.usedBytes();
|
||||
root["heap_total"] = ESP.getHeapSize();
|
||||
root["heap_used"] = ESP.getHeapSize() - ESP.getFreeHeap();
|
||||
root["sketch_total"] = ESP.getFreeSketchSpace();
|
||||
root["sketch_used"] = ESP.getSketchSize();
|
||||
root["littlefs_total"] = LittleFS.totalBytes();
|
||||
root["littlefs_used"] = LittleFS.usedBytes();
|
||||
|
||||
root[F("chiprevision")] = ESP.getChipRevision();
|
||||
root[F("chipmodel")] = ESP.getChipModel();
|
||||
root[F("chipcores")] = ESP.getChipCores();
|
||||
root["chiprevision"] = ESP.getChipRevision();
|
||||
root["chipmodel"] = ESP.getChipModel();
|
||||
root["chipcores"] = ESP.getChipCores();
|
||||
|
||||
String reason;
|
||||
reason = ResetReason.get_reset_reason_verbose(0);
|
||||
root[F("resetreason_0")] = reason;
|
||||
root["resetreason_0"] = reason;
|
||||
|
||||
reason = ResetReason.get_reset_reason_verbose(1);
|
||||
root[F("resetreason_1")] = reason;
|
||||
root["resetreason_1"] = reason;
|
||||
|
||||
root[F("cfgsavecount")] = Configuration.get().Cfg_SaveCount;
|
||||
root["cfgsavecount"] = Configuration.get().Cfg_SaveCount;
|
||||
|
||||
char version[16];
|
||||
snprintf(version, sizeof(version), "%d.%d.%d", CONFIG_VERSION >> 24 & 0xff, CONFIG_VERSION >> 16 & 0xff, CONFIG_VERSION >> 8 & 0xff);
|
||||
root[F("config_version")] = version;
|
||||
root[F("git_hash")] = AUTO_GIT_HASH;
|
||||
root["config_version"] = version;
|
||||
root["git_hash"] = AUTO_GIT_HASH;
|
||||
|
||||
root[F("uptime")] = esp_timer_get_time() / 1000000;
|
||||
root["uptime"] = esp_timer_get_time() / 1000000;
|
||||
|
||||
root[F("radio_connected")] = Hoymiles.getRadio()->isConnected();
|
||||
root[F("radio_pvariant")] = Hoymiles.getRadio()->isPVariant();
|
||||
root["radio_connected"] = Hoymiles.getRadio()->isConnected();
|
||||
root["radio_pvariant"] = Hoymiles.getRadio()->isPVariant();
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
@ -103,17 +103,17 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
|
||||
|
||||
JsonObject invObject = invArray.createNestedObject();
|
||||
|
||||
invObject[F("serial")] = inv->serialString();
|
||||
invObject[F("name")] = inv->name();
|
||||
invObject[F("data_age")] = (millis() - inv->Statistics()->getLastUpdate()) / 1000;
|
||||
invObject[F("poll_enabled")] = inv->getEnablePolling();
|
||||
invObject[F("reachable")] = inv->isReachable();
|
||||
invObject[F("producing")] = inv->isProducing();
|
||||
invObject[F("limit_relative")] = inv->SystemConfigPara()->getLimitPercent();
|
||||
invObject["serial"] = inv->serialString();
|
||||
invObject["name"] = inv->name();
|
||||
invObject["data_age"] = (millis() - inv->Statistics()->getLastUpdate()) / 1000;
|
||||
invObject["poll_enabled"] = inv->getEnablePolling();
|
||||
invObject["reachable"] = inv->isReachable();
|
||||
invObject["producing"] = inv->isProducing();
|
||||
invObject["limit_relative"] = inv->SystemConfigPara()->getLimitPercent();
|
||||
if (inv->DevInfo()->getMaxPower() > 0) {
|
||||
invObject[F("limit_absolute")] = inv->SystemConfigPara()->getLimitPercent() * inv->DevInfo()->getMaxPower() / 100.0;
|
||||
invObject["limit_absolute"] = inv->SystemConfigPara()->getLimitPercent() * inv->DevInfo()->getMaxPower() / 100.0;
|
||||
} else {
|
||||
invObject[F("limit_absolute")] = -1;
|
||||
invObject["limit_absolute"] = -1;
|
||||
}
|
||||
|
||||
// Loop all channels
|
||||
@ -123,14 +123,14 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
|
||||
if (t == TYPE_DC) {
|
||||
INVERTER_CONFIG_T* inv_cfg = Configuration.getInverterConfig(inv->serial());
|
||||
if (inv_cfg != nullptr) {
|
||||
chanTypeObj[String(static_cast<uint8_t>(c))][F("name")]["u"] = inv_cfg->channel[c].Name;
|
||||
chanTypeObj[String(static_cast<uint8_t>(c))]["name"]["u"] = inv_cfg->channel[c].Name;
|
||||
}
|
||||
}
|
||||
addField(chanTypeObj, i, inv, t, c, FLD_PAC);
|
||||
addField(chanTypeObj, i, inv, t, c, FLD_UAC);
|
||||
addField(chanTypeObj, i, inv, t, c, FLD_IAC);
|
||||
if (t == TYPE_AC) {
|
||||
addField(chanTypeObj, i, inv, t, c, FLD_PDC, F("Power DC"));
|
||||
addField(chanTypeObj, i, inv, t, c, FLD_PDC, "Power DC");
|
||||
} else {
|
||||
addField(chanTypeObj, i, inv, t, c, FLD_PDC);
|
||||
}
|
||||
@ -150,9 +150,9 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
|
||||
}
|
||||
|
||||
if (inv->Statistics()->hasChannelFieldValue(TYPE_INV, CH0, FLD_EVT_LOG)) {
|
||||
invObject[F("events")] = inv->EventLog()->getEntryCount();
|
||||
invObject["events"] = inv->EventLog()->getEntryCount();
|
||||
} else {
|
||||
invObject[F("events")] = -1;
|
||||
invObject["events"] = -1;
|
||||
}
|
||||
|
||||
if (inv->Statistics()->getLastUpdate() > _newestInverterTimestamp) {
|
||||
@ -174,12 +174,12 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
|
||||
|
||||
JsonObject hintObj = root.createNestedObject("hints");
|
||||
struct tm timeinfo;
|
||||
hintObj[F("time_sync")] = !getLocalTime(&timeinfo, 5);
|
||||
hintObj[F("radio_problem")] = (!Hoymiles.getRadio()->isConnected() || !Hoymiles.getRadio()->isPVariant());
|
||||
hintObj["time_sync"] = !getLocalTime(&timeinfo, 5);
|
||||
hintObj["radio_problem"] = (!Hoymiles.getRadio()->isConnected() || !Hoymiles.getRadio()->isPVariant());
|
||||
if (!strcmp(Configuration.get().Security_Password, ACCESS_POINT_PASSWORD)) {
|
||||
hintObj[F("default_password")] = true;
|
||||
hintObj["default_password"] = true;
|
||||
} else {
|
||||
hintObj[F("default_password")] = false;
|
||||
hintObj["default_password"] = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
58
src/main.cpp
58
src/main.cpp
@ -27,80 +27,80 @@ void setup()
|
||||
while (!Serial)
|
||||
yield();
|
||||
MessageOutput.println();
|
||||
MessageOutput.println(F("Starting OpenDTU"));
|
||||
MessageOutput.println("Starting OpenDTU");
|
||||
|
||||
// Initialize file system
|
||||
MessageOutput.print(F("Initialize FS... "));
|
||||
MessageOutput.print("Initialize FS... ");
|
||||
if (!LittleFS.begin(false)) { // Do not format if mount failed
|
||||
MessageOutput.print(F("failed... trying to format..."));
|
||||
MessageOutput.print("failed... trying to format...");
|
||||
if (!LittleFS.begin(true)) {
|
||||
MessageOutput.print("success");
|
||||
} else {
|
||||
MessageOutput.print("failed");
|
||||
}
|
||||
} else {
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
}
|
||||
|
||||
// Read configuration values
|
||||
MessageOutput.print(F("Reading configuration... "));
|
||||
MessageOutput.print("Reading configuration... ");
|
||||
if (!Configuration.read()) {
|
||||
MessageOutput.print(F("initializing... "));
|
||||
MessageOutput.print("initializing... ");
|
||||
Configuration.init();
|
||||
if (Configuration.write()) {
|
||||
MessageOutput.print(F("written... "));
|
||||
MessageOutput.print("written... ");
|
||||
} else {
|
||||
MessageOutput.print(F("failed... "));
|
||||
MessageOutput.print("failed... ");
|
||||
}
|
||||
}
|
||||
if (Configuration.get().Cfg_Version != CONFIG_VERSION) {
|
||||
MessageOutput.print(F("migrated... "));
|
||||
MessageOutput.print("migrated... ");
|
||||
Configuration.migrate();
|
||||
}
|
||||
CONFIG_T& config = Configuration.get();
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
|
||||
// Load PinMapping
|
||||
MessageOutput.print(F("Reading PinMapping... "));
|
||||
MessageOutput.print("Reading PinMapping... ");
|
||||
if (PinMapping.init(String(Configuration.get().Dev_PinMapping))) {
|
||||
MessageOutput.print(F("found valid mapping "));
|
||||
MessageOutput.print("found valid mapping ");
|
||||
} else {
|
||||
MessageOutput.print(F("using default config "));
|
||||
MessageOutput.print("using default config ");
|
||||
}
|
||||
const PinMapping_t& pin = PinMapping.get();
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
|
||||
// Initialize WiFi
|
||||
MessageOutput.print(F("Initialize Network... "));
|
||||
MessageOutput.print("Initialize Network... ");
|
||||
NetworkSettings.init();
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
NetworkSettings.applyConfig();
|
||||
|
||||
// Initialize NTP
|
||||
MessageOutput.print(F("Initialize NTP... "));
|
||||
MessageOutput.print("Initialize NTP... ");
|
||||
NtpSettings.init();
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
|
||||
// Initialize SunPosition
|
||||
MessageOutput.print(F("Initialize SunPosition... "));
|
||||
MessageOutput.print("Initialize SunPosition... ");
|
||||
SunPosition.init();
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
|
||||
// Initialize MqTT
|
||||
MessageOutput.print(F("Initialize MqTT... "));
|
||||
MessageOutput.print("Initialize MqTT... ");
|
||||
MqttSettings.init();
|
||||
MqttHandleDtu.init();
|
||||
MqttHandleInverter.init();
|
||||
MqttHandleHass.init();
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
|
||||
// Initialize WebApi
|
||||
MessageOutput.print(F("Initialize WebApi... "));
|
||||
MessageOutput.print("Initialize WebApi... ");
|
||||
WebApi.init();
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
|
||||
// Initialize Display
|
||||
MessageOutput.print(F("Initialize Display... "));
|
||||
MessageOutput.print("Initialize Display... ");
|
||||
Display.init(
|
||||
static_cast<DisplayType_t>(pin.display_type),
|
||||
pin.display_data,
|
||||
@ -112,12 +112,12 @@ void setup()
|
||||
Display.enableScreensaver = config.Display_ScreenSaver;
|
||||
Display.setContrast(config.Display_Contrast);
|
||||
Display.setStartupDisplay();
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
|
||||
// Check for default DTU serial
|
||||
MessageOutput.print(F("Check for default DTU serial... "));
|
||||
MessageOutput.print("Check for default DTU serial... ");
|
||||
if (config.Dtu_Serial == DTU_SERIAL) {
|
||||
MessageOutput.print(F("generate serial based on ESP chip id: "));
|
||||
MessageOutput.print("generate serial based on ESP chip id: ");
|
||||
uint64_t dtuId = Utils::generateDtuSerial();
|
||||
MessageOutput.printf("%0x%08x... ",
|
||||
((uint32_t)((dtuId >> 32) & 0xFFFFFFFF)),
|
||||
@ -125,7 +125,7 @@ void setup()
|
||||
config.Dtu_Serial = dtuId;
|
||||
Configuration.write();
|
||||
}
|
||||
MessageOutput.println(F("done"));
|
||||
MessageOutput.println("done");
|
||||
|
||||
InverterSettings.init();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user