Remove not required F() macro. Frees ~20kb flash.

This commit is contained in:
Thomas Basler 2023-04-04 18:51:18 +02:00 committed by helgeerbe
parent dab5b4d723
commit ca0b8e9afc
33 changed files with 868 additions and 868 deletions

View File

@ -35,7 +35,7 @@ void HoymilesClass::loop()
if (_radio->isIdle()) { if (_radio->isIdle()) {
std::shared_ptr<InverterAbstract> iv = getInverterByPos(inverterPos); std::shared_ptr<InverterAbstract> iv = getInverterByPos(inverterPos);
if (iv != nullptr) { if (iv != nullptr) {
_messageOutput->print(F("Fetch inverter: ")); _messageOutput->print("Fetch inverter: ");
_messageOutput->println(iv->serial(), HEX); _messageOutput->println(iv->serial(), HEX);
iv->sendStatsRequest(_radio.get()); iv->sendStatsRequest(_radio.get());
@ -54,19 +54,19 @@ void HoymilesClass::loop()
// Set limit if required // Set limit if required
if (iv->SystemConfigPara()->getLastLimitCommandSuccess() == CMD_NOK) { if (iv->SystemConfigPara()->getLastLimitCommandSuccess() == CMD_NOK) {
_messageOutput->println(F("Resend ActivePowerControl")); _messageOutput->println("Resend ActivePowerControl");
iv->resendActivePowerControlRequest(_radio.get()); iv->resendActivePowerControlRequest(_radio.get());
} }
// Set power status if required // Set power status if required
if (iv->PowerCommand()->getLastPowerCommandSuccess() == CMD_NOK) { if (iv->PowerCommand()->getLastPowerCommandSuccess() == CMD_NOK) {
_messageOutput->println(F("Resend PowerCommand")); _messageOutput->println("Resend PowerCommand");
iv->resendPowerControlRequest(_radio.get()); iv->resendPowerControlRequest(_radio.get());
} }
// Fetch dev info (but first fetch stats) // Fetch dev info (but first fetch stats)
if (iv->Statistics()->getLastUpdate() > 0 && (iv->DevInfo()->getLastUpdateAll() == 0 || iv->DevInfo()->getLastUpdateSimple() == 0)) { 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()); iv->sendDevInfoRequest(_radio.get());
} }
} }

View File

@ -25,9 +25,9 @@ void HoymilesRadio::init(SPIClass* initialisedSpiBus, uint8_t pinCE, uint8_t pin
_radio->setRetries(0, 0); _radio->setRetries(0, 0);
_radio->maskIRQ(true, true, false); // enable only receiving interrupts _radio->maskIRQ(true, true, false); // enable only receiving interrupts
if (_radio->isChipConnected()) { if (_radio->isChipConnected()) {
Hoymiles.getMessageOutput()->println(F("Connection successful")); Hoymiles.getMessageOutput()->println("Connection successful");
} else { } else {
Hoymiles.getMessageOutput()->println(F("Connection error!!")); Hoymiles.getMessageOutput()->println("Connection error!!");
} }
attachInterrupt(digitalPinToInterrupt(pinIRQ), std::bind(&HoymilesRadio::handleIntr, this), FALLING); attachInterrupt(digitalPinToInterrupt(pinIRQ), std::bind(&HoymilesRadio::handleIntr, this), FALLING);
@ -44,7 +44,7 @@ void HoymilesRadio::loop()
} }
if (_packetReceived) { if (_packetReceived) {
Hoymiles.getMessageOutput()->println(F("Interrupt received")); Hoymiles.getMessageOutput()->println("Interrupt received");
while (_radio->available()) { while (_radio->available()) {
if (!(_rxBuffer.size() > FRAGMENT_BUFFER_SIZE)) { if (!(_rxBuffer.size() > FRAGMENT_BUFFER_SIZE)) {
fragment_t f; fragment_t f;
@ -56,7 +56,7 @@ void HoymilesRadio::loop()
_radio->read(f.fragment, f.len); _radio->read(f.fragment, f.len);
_rxBuffer.push(f); _rxBuffer.push(f);
} else { } else {
Hoymiles.getMessageOutput()->println(F("Buffer full")); Hoymiles.getMessageOutput()->println("Buffer full");
_radio->flush_rx(); _radio->flush_rx();
} }
} }
@ -76,11 +76,11 @@ void HoymilesRadio::loop()
dumpBuf(buf, f.fragment, f.len); dumpBuf(buf, f.fragment, f.len);
inv->addRxFragment(f.fragment, f.len); inv->addRxFragment(f.fragment, f.len);
} else { } else {
Hoymiles.getMessageOutput()->println(F("Inverter Not found!")); Hoymiles.getMessageOutput()->println("Inverter Not found!");
} }
} else { } else {
Hoymiles.getMessageOutput()->println(F("Frame kaputt")); Hoymiles.getMessageOutput()->println("Frame kaputt");
} }
// Remove paket from buffer even it was corrupted // Remove paket from buffer even it was corrupted
@ -89,46 +89,46 @@ void HoymilesRadio::loop()
} }
if (_busyFlag && _rxTimeout.occured()) { 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()); std::shared_ptr<InverterAbstract> inv = Hoymiles.getInverterBySerial(_commandQueue.front().get()->getTargetAddress());
if (nullptr != inv) { if (nullptr != inv) {
CommandAbstract* cmd = _commandQueue.front().get(); CommandAbstract* cmd = _commandQueue.front().get();
uint8_t verifyResult = inv->verifyAllFragments(cmd); uint8_t verifyResult = inv->verifyAllFragments(cmd);
if (verifyResult == FRAGMENT_ALL_MISSING_RESEND) { if (verifyResult == FRAGMENT_ALL_MISSING_RESEND) {
Hoymiles.getMessageOutput()->println(F("Nothing received, resend whole request")); Hoymiles.getMessageOutput()->println("Nothing received, resend whole request");
sendLastPacketAgain(); sendLastPacketAgain();
} else if (verifyResult == FRAGMENT_ALL_MISSING_TIMEOUT) { } 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(); _commandQueue.pop();
_busyFlag = false; _busyFlag = false;
} else if (verifyResult == FRAGMENT_RETRANSMIT_TIMEOUT) { } else if (verifyResult == FRAGMENT_RETRANSMIT_TIMEOUT) {
Hoymiles.getMessageOutput()->println(F("Retransmit timeout")); Hoymiles.getMessageOutput()->println("Retransmit timeout");
_commandQueue.pop(); _commandQueue.pop();
_busyFlag = false; _busyFlag = false;
} else if (verifyResult == FRAGMENT_HANDLE_ERROR) { } else if (verifyResult == FRAGMENT_HANDLE_ERROR) {
Hoymiles.getMessageOutput()->println(F("Packet handling error")); Hoymiles.getMessageOutput()->println("Packet handling error");
_commandQueue.pop(); _commandQueue.pop();
_busyFlag = false; _busyFlag = false;
} else if (verifyResult > 0) { } else if (verifyResult > 0) {
// Perform Retransmit // Perform Retransmit
Hoymiles.getMessageOutput()->print(F("Request retransmit: ")); Hoymiles.getMessageOutput()->print("Request retransmit: ");
Hoymiles.getMessageOutput()->println(verifyResult); Hoymiles.getMessageOutput()->println(verifyResult);
sendRetransmitPacket(verifyResult); sendRetransmitPacket(verifyResult);
} else { } else {
// Successful received all packages // Successful received all packages
Hoymiles.getMessageOutput()->println(F("Success")); Hoymiles.getMessageOutput()->println("Success");
_commandQueue.pop(); _commandQueue.pop();
_busyFlag = false; _busyFlag = false;
} }
} else { } else {
// If inverter was not found, assume the command is invalid // 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(); _commandQueue.pop();
_busyFlag = false; _busyFlag = false;
} }
@ -142,7 +142,7 @@ void HoymilesRadio::loop()
inv->clearRxFragmentBuffer(); inv->clearRxFragmentBuffer();
sendEsbPacket(cmd); sendEsbPacket(cmd);
} else { } else {
Hoymiles.getMessageOutput()->println(F("TX: Invalid inverter found")); Hoymiles.getMessageOutput()->println("TX: Invalid inverter found");
_commandQueue.pop(); _commandQueue.pop();
} }
} }
@ -252,11 +252,11 @@ void HoymilesRadio::sendEsbPacket(CommandAbstract* cmd)
openWritingPipe(s); openWritingPipe(s);
_radio->setRetries(3, 15); _radio->setRetries(3, 15);
Hoymiles.getMessageOutput()->print(F("TX ")); Hoymiles.getMessageOutput()->print("TX ");
Hoymiles.getMessageOutput()->print(cmd->getCommandName()); Hoymiles.getMessageOutput()->print(cmd->getCommandName());
Hoymiles.getMessageOutput()->print(F(" Channel: ")); Hoymiles.getMessageOutput()->print(" Channel: ");
Hoymiles.getMessageOutput()->print(_radio->getChannel()); Hoymiles.getMessageOutput()->print(_radio->getChannel());
Hoymiles.getMessageOutput()->print(F(" --> ")); Hoymiles.getMessageOutput()->print(" --> ");
cmd->dumpDataPayload(Hoymiles.getMessageOutput()); cmd->dumpDataPayload(Hoymiles.getMessageOutput());
_radio->write(cmd->getDataPayload(), cmd->getDataSize()); _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++) { for (uint8_t i = 0; i < len; i++) {
Hoymiles.getMessageOutput()->printf("%02X ", buf[i]); Hoymiles.getMessageOutput()->printf("%02X ", buf[i]);
} }
Hoymiles.getMessageOutput()->println(F("")); Hoymiles.getMessageOutput()->println("");
} }

View File

@ -29,7 +29,7 @@ bool HM_1CH::isValidSerial(uint64_t serial)
String HM_1CH::typeName() 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() const std::list<byteAssign_t>* HM_1CH::getByteAssignment()

View File

@ -30,7 +30,7 @@ bool HM_2CH::isValidSerial(uint64_t serial)
String HM_2CH::typeName() 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() const std::list<byteAssign_t>* HM_2CH::getByteAssignment()

View File

@ -29,7 +29,7 @@ bool HM_4CH::isValidSerial(uint64_t serial)
String HM_4CH::typeName() 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() const std::list<byteAssign_t>* HM_4CH::getByteAssignment()

View File

@ -169,7 +169,7 @@ uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd)
{ {
// All missing // All missing
if (_rxFragmentLastPacketId == 0) { if (_rxFragmentLastPacketId == 0) {
Hoymiles.getMessageOutput()->println(F("All missing")); Hoymiles.getMessageOutput()->println("All missing");
if (cmd->getSendCount() <= MAX_RESEND_COUNT) { if (cmd->getSendCount() <= MAX_RESEND_COUNT) {
return FRAGMENT_ALL_MISSING_RESEND; return FRAGMENT_ALL_MISSING_RESEND;
} else { } else {
@ -180,7 +180,7 @@ uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd)
// Last fragment is missing (the one with 0x80) // Last fragment is missing (the one with 0x80)
if (_rxFragmentMaxPacketId == 0) { if (_rxFragmentMaxPacketId == 0) {
Hoymiles.getMessageOutput()->println(F("Last missing")); Hoymiles.getMessageOutput()->println("Last missing");
if (_rxFragmentRetransmitCnt++ < MAX_RETRANSMIT_COUNT) { if (_rxFragmentRetransmitCnt++ < MAX_RETRANSMIT_COUNT) {
return _rxFragmentLastPacketId + 1; return _rxFragmentLastPacketId + 1;
} else { } else {
@ -192,7 +192,7 @@ uint8_t InverterAbstract::verifyAllFragments(CommandAbstract* cmd)
// Middle fragment is missing // Middle fragment is missing
for (uint8_t i = 0; i < _rxFragmentMaxPacketId - 1; i++) { for (uint8_t i = 0; i < _rxFragmentMaxPacketId - 1; i++) {
if (!_rxFragmentBuffer[i].wasReceived) { if (!_rxFragmentBuffer[i].wasReceived) {
Hoymiles.getMessageOutput()->println(F("Middle missing")); Hoymiles.getMessageOutput()->println("Middle missing");
if (_rxFragmentRetransmitCnt++ < MAX_RETRANSMIT_COUNT) { if (_rxFragmentRetransmitCnt++ < MAX_RETRANSMIT_COUNT) {
return i + 1; return i + 1;
} else { } else {

View File

@ -64,214 +64,214 @@ void AlarmLogParser::getLogEntry(uint8_t entryId, AlarmLogEntry_t* entry)
switch (entry->MessageId) { switch (entry->MessageId) {
case 1: case 1:
entry->Message = F("Inverter start"); entry->Message = "Inverter start";
break; break;
case 2: case 2:
entry->Message = F("DTU command failed"); entry->Message = "DTU command failed";
break; break;
case 121: case 121:
entry->Message = F("Over temperature protection"); entry->Message = "Over temperature protection";
break; break;
case 124: case 124:
entry->Message = F("Shut down by remote control"); entry->Message = "Shut down by remote control";
break; break;
case 125: case 125:
entry->Message = F("Grid configuration parameter error"); entry->Message = "Grid configuration parameter error";
break; break;
case 126: case 126:
entry->Message = F("Software error code 126"); entry->Message = "Software error code 126";
break; break;
case 127: case 127:
entry->Message = F("Firmware error"); entry->Message = "Firmware error";
break; break;
case 128: case 128:
entry->Message = F("Software error code 128"); entry->Message = "Software error code 128";
break; break;
case 129: case 129:
entry->Message = F("Abnormal bias"); entry->Message = "Abnormal bias";
break; break;
case 130: case 130:
entry->Message = F("Offline"); entry->Message = "Offline";
break; break;
case 141: case 141:
entry->Message = F("Grid: Grid overvoltage"); entry->Message = "Grid: Grid overvoltage";
break; break;
case 142: case 142:
entry->Message = F("Grid: 10 min value grid overvoltage"); entry->Message = "Grid: 10 min value grid overvoltage";
break; break;
case 143: case 143:
entry->Message = F("Grid: Grid undervoltage"); entry->Message = "Grid: Grid undervoltage";
break; break;
case 144: case 144:
entry->Message = F("Grid: Grid overfrequency"); entry->Message = "Grid: Grid overfrequency";
break; break;
case 145: case 145:
entry->Message = F("Grid: Grid underfrequency"); entry->Message = "Grid: Grid underfrequency";
break; break;
case 146: case 146:
entry->Message = F("Grid: Rapid grid frequency change rate"); entry->Message = "Grid: Rapid grid frequency change rate";
break; break;
case 147: case 147:
entry->Message = F("Grid: Power grid outage"); entry->Message = "Grid: Power grid outage";
break; break;
case 148: case 148:
entry->Message = F("Grid: Grid disconnection"); entry->Message = "Grid: Grid disconnection";
break; break;
case 149: case 149:
entry->Message = F("Grid: Island detected"); entry->Message = "Grid: Island detected";
break; break;
case 205: case 205:
entry->Message = F("MPPT-A: Input overvoltage"); entry->Message = "MPPT-A: Input overvoltage";
break; break;
case 206: case 206:
entry->Message = F("MPPT-B: Input overvoltage"); entry->Message = "MPPT-B: Input overvoltage";
break; break;
case 207: case 207:
entry->Message = F("MPPT-A: Input undervoltage"); entry->Message = "MPPT-A: Input undervoltage";
break; break;
case 208: case 208:
entry->Message = F("MPPT-B: Input undervoltage"); entry->Message = "MPPT-B: Input undervoltage";
break; break;
case 209: case 209:
entry->Message = F("PV-1: No input"); entry->Message = "PV-1: No input";
break; break;
case 210: case 210:
entry->Message = F("PV-2: No input"); entry->Message = "PV-2: No input";
break; break;
case 211: case 211:
entry->Message = F("PV-3: No input"); entry->Message = "PV-3: No input";
break; break;
case 212: case 212:
entry->Message = F("PV-4: No input"); entry->Message = "PV-4: No input";
break; break;
case 213: case 213:
entry->Message = F("MPPT-A: PV-1 & PV-2 abnormal wiring"); entry->Message = "MPPT-A: PV-1 & PV-2 abnormal wiring";
break; break;
case 214: case 214:
entry->Message = F("MPPT-B: PV-3 & PV-4 abnormal wiring"); entry->Message = "MPPT-B: PV-3 & PV-4 abnormal wiring";
break; break;
case 215: case 215:
entry->Message = F("PV-1: Input overvoltage"); entry->Message = "PV-1: Input overvoltage";
break; break;
case 216: case 216:
entry->Message = F("PV-1: Input undervoltage"); entry->Message = "PV-1: Input undervoltage";
break; break;
case 217: case 217:
entry->Message = F("PV-2: Input overvoltage"); entry->Message = "PV-2: Input overvoltage";
break; break;
case 218: case 218:
entry->Message = F("PV-2: Input undervoltage"); entry->Message = "PV-2: Input undervoltage";
break; break;
case 219: case 219:
entry->Message = F("PV-3: Input overvoltage"); entry->Message = "PV-3: Input overvoltage";
break; break;
case 220: case 220:
entry->Message = F("PV-3: Input undervoltage"); entry->Message = "PV-3: Input undervoltage";
break; break;
case 221: case 221:
entry->Message = F("PV-4: Input overvoltage"); entry->Message = "PV-4: Input overvoltage";
break; break;
case 222: case 222:
entry->Message = F("PV-4: Input undervoltage"); entry->Message = "PV-4: Input undervoltage";
break; break;
case 301: case 301:
entry->Message = F("Hardware error code 301"); entry->Message = "Hardware error code 301";
break; break;
case 302: case 302:
entry->Message = F("Hardware error code 302"); entry->Message = "Hardware error code 302";
break; break;
case 303: case 303:
entry->Message = F("Hardware error code 303"); entry->Message = "Hardware error code 303";
break; break;
case 304: case 304:
entry->Message = F("Hardware error code 304"); entry->Message = "Hardware error code 304";
break; break;
case 305: case 305:
entry->Message = F("Hardware error code 305"); entry->Message = "Hardware error code 305";
break; break;
case 306: case 306:
entry->Message = F("Hardware error code 306"); entry->Message = "Hardware error code 306";
break; break;
case 307: case 307:
entry->Message = F("Hardware error code 307"); entry->Message = "Hardware error code 307";
break; break;
case 308: case 308:
entry->Message = F("Hardware error code 308"); entry->Message = "Hardware error code 308";
break; break;
case 309: case 309:
entry->Message = F("Hardware error code 309"); entry->Message = "Hardware error code 309";
break; break;
case 310: case 310:
entry->Message = F("Hardware error code 310"); entry->Message = "Hardware error code 310";
break; break;
case 311: case 311:
entry->Message = F("Hardware error code 311"); entry->Message = "Hardware error code 311";
break; break;
case 312: case 312:
entry->Message = F("Hardware error code 312"); entry->Message = "Hardware error code 312";
break; break;
case 313: case 313:
entry->Message = F("Hardware error code 313"); entry->Message = "Hardware error code 313";
break; break;
case 314: case 314:
entry->Message = F("Hardware error code 314"); entry->Message = "Hardware error code 314";
break; break;
case 5041: case 5041:
entry->Message = F("Error code-04 Port 1"); entry->Message = "Error code-04 Port 1";
break; break;
case 5042: case 5042:
entry->Message = F("Error code-04 Port 2"); entry->Message = "Error code-04 Port 2";
break; break;
case 5043: case 5043:
entry->Message = F("Error code-04 Port 3"); entry->Message = "Error code-04 Port 3";
break; break;
case 5044: case 5044:
entry->Message = F("Error code-04 Port 4"); entry->Message = "Error code-04 Port 4";
break; break;
case 5051: case 5051:
entry->Message = F("PV Input 1 Overvoltage/Undervoltage"); entry->Message = "PV Input 1 Overvoltage/Undervoltage";
break; break;
case 5052: case 5052:
entry->Message = F("PV Input 2 Overvoltage/Undervoltage"); entry->Message = "PV Input 2 Overvoltage/Undervoltage";
break; break;
case 5053: case 5053:
entry->Message = F("PV Input 3 Overvoltage/Undervoltage"); entry->Message = "PV Input 3 Overvoltage/Undervoltage";
break; break;
case 5054: case 5054:
entry->Message = F("PV Input 4 Overvoltage/Undervoltage"); entry->Message = "PV Input 4 Overvoltage/Undervoltage";
break; break;
case 5060: case 5060:
entry->Message = F("Abnormal bias"); entry->Message = "Abnormal bias";
break; break;
case 5070: case 5070:
entry->Message = F("Over temperature protection"); entry->Message = "Over temperature protection";
break; break;
case 5080: case 5080:
entry->Message = F("Grid Overvoltage/Undervoltage"); entry->Message = "Grid Overvoltage/Undervoltage";
break; break;
case 5090: case 5090:
entry->Message = F("Grid Overfrequency/Underfrequency"); entry->Message = "Grid Overfrequency/Underfrequency";
break; break;
case 5100: case 5100:
entry->Message = F("Island detected"); entry->Message = "Island detected";
break; break;
case 5120: case 5120:
entry->Message = F("EEPROM reading and writing error"); entry->Message = "EEPROM reading and writing error";
break; break;
case 5150: case 5150:
entry->Message = F("10 min value grid overvoltage"); entry->Message = "10 min value grid overvoltage";
break; break;
case 5200: case 5200:
entry->Message = F("Firmware error"); entry->Message = "Firmware error";
break; break;
case 8310: case 8310:
entry->Message = F("Shut down"); entry->Message = "Shut down";
break; break;
case 9000: case 9000:
entry->Message = F("Microinverter is suspected of being stolen"); entry->Message = "Microinverter is suspected of being stolen";
break; break;
default: default:
entry->Message = F("Unknown"); entry->Message = "Unknown";
break; break;
} }
} }

View File

@ -29,58 +29,58 @@ String ResetReasonClass::get_reset_reason_verbose(uint8_t cpu_id)
switch (reason) { switch (reason) {
case 1: case 1:
reason_str = F("Vbat power on reset"); reason_str = "Vbat power on reset";
break; break;
case 3: case 3:
reason_str = F("Software reset digital core"); reason_str = "Software reset digital core";
break; break;
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
case 4: case 4:
reason_str = F("Legacy watch dog reset digital core"); reason_str = "Legacy watch dog reset digital core";
break; break;
#endif #endif
case 5: case 5:
reason_str = F("Deep Sleep reset digital core"); reason_str = "Deep Sleep reset digital core";
break; break;
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
case 6: case 6:
reason_str = F("Reset by SLC module, reset digital core"); reason_str = "Reset by SLC module, reset digital core";
break; break;
#endif #endif
case 7: case 7:
reason_str = F("Timer Group0 Watch dog reset digital core"); reason_str = "Timer Group0 Watch dog reset digital core";
break; break;
case 8: case 8:
reason_str = F("Timer Group1 Watch dog reset digital core"); reason_str = "Timer Group1 Watch dog reset digital core";
break; break;
case 9: case 9:
reason_str = F("RTC Watch dog Reset digital core"); reason_str = "RTC Watch dog Reset digital core";
break; break;
case 10: case 10:
reason_str = F("Instrusion tested to reset CPU"); reason_str = "Instrusion tested to reset CPU";
break; break;
case 11: case 11:
reason_str = F("Time Group reset CPU"); reason_str = "Time Group reset CPU";
break; break;
case 12: case 12:
reason_str = F("Software reset CPU"); reason_str = "Software reset CPU";
break; break;
case 13: case 13:
reason_str = F("RTC Watch dog Reset CPU"); reason_str = "RTC Watch dog Reset CPU";
break; break;
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
case 14: case 14:
reason_str = F("for APP CPU, reset by PRO CPU"); reason_str = "for APP CPU, reset by PRO CPU";
break; break;
#endif #endif
case 15: case 15:
reason_str = F("Reset when the vdd voltage is not stable"); reason_str = "Reset when the vdd voltage is not stable";
break; break;
case 16: 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; break;
default: default:
reason_str = F("NO_MEAN"); reason_str = "NO_MEAN";
} }
return reason_str; return reason_str;
@ -95,58 +95,58 @@ String ResetReasonClass::get_reset_reason_short(uint8_t cpu_id)
switch (reason) { switch (reason) {
case 1: case 1:
reason_str = F("POWERON_RESET"); reason_str = "POWERON_RESET";
break; break;
case 3: case 3:
reason_str = F("SW_RESET"); reason_str = "SW_RESET";
break; break;
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
case 4: case 4:
reason_str = F("OWDT_RESET"); reason_str = "OWDT_RESET";
break; break;
#endif #endif
case 5: case 5:
reason_str = F("DEEPSLEEP_RESET"); reason_str = "DEEPSLEEP_RESET";
break; break;
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
case 6: case 6:
reason_str = F("SDIO_RESET"); reason_str = "SDIO_RESET";
break; break;
#endif #endif
case 7: case 7:
reason_str = F("TG0WDT_SYS_RESET"); reason_str = "TG0WDT_SYS_RESET";
break; break;
case 8: case 8:
reason_str = F("TG1WDT_SYS_RESET"); reason_str = "TG1WDT_SYS_RESET";
break; break;
case 9: case 9:
reason_str = F("RTCWDT_SYS_RESET"); reason_str = "RTCWDT_SYS_RESET";
break; break;
case 10: case 10:
reason_str = F("INTRUSION_RESET"); reason_str = "INTRUSION_RESET";
break; break;
case 11: case 11:
reason_str = F("TGWDT_CPU_RESET"); reason_str = "TGWDT_CPU_RESET";
break; break;
case 12: case 12:
reason_str = F("SW_CPU_RESET"); reason_str = "SW_CPU_RESET";
break; break;
case 13: case 13:
reason_str = F("RTCWDT_CPU_RESET"); reason_str = "RTCWDT_CPU_RESET";
break; break;
#if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) && !defined(CONFIG_IDF_TARGET_ESP32S2)
case 14: case 14:
reason_str = F("EXT_CPU_RESET"); reason_str = "EXT_CPU_RESET";
break; break;
#endif #endif
case 15: case 15:
reason_str = F("RTCWDT_BROWN_OUT_RESET"); reason_str = "RTCWDT_BROWN_OUT_RESET";
break; break;
case 16: case 16:
reason_str = F("RTCWDT_RTC_RESET"); reason_str = "RTCWDT_RTC_RESET";
break; break;
default: default:
reason_str = F("NO_MEAN"); reason_str = "NO_MEAN";
} }
return reason_str; return reason_str;

View File

@ -180,7 +180,7 @@ bool ConfigurationClass::read()
// Deserialize the JSON document // Deserialize the JSON document
DeserializationError error = deserializeJson(doc, f); DeserializationError error = deserializeJson(doc, f);
if (error) { if (error) {
MessageOutput.printf("Failed to read file, using default configuration. Error: %s (capacity: %d)\r\n", error.c_str(), doc.capacity()); MessageOutput.println("Failed to read file, using default configuration");
} }
JsonObject cfg = doc["cfg"]; JsonObject cfg = doc["cfg"];
@ -359,7 +359,7 @@ void ConfigurationClass::migrate()
{ {
File f = LittleFS.open(CONFIG_FILENAME, "r", false); File f = LittleFS.open(CONFIG_FILENAME, "r", false);
if (!f) { if (!f) {
MessageOutput.println(F("Failed to open file, cancel migration")); MessageOutput.println("Failed to open file, cancel migration");
return; return;
} }

View File

@ -21,27 +21,27 @@ void InverterSettingsClass::init()
const PinMapping_t& pin = PinMapping.get(); const PinMapping_t& pin = PinMapping.get();
// Initialize inverter communication // Initialize inverter communication
MessageOutput.print(F("Initialize Hoymiles interface... ")); MessageOutput.print("Initialize Hoymiles interface... ");
if (PinMapping.isValidNrf24Config()) { if (PinMapping.isValidNrf24Config()) {
SPIClass* spiClass = new SPIClass(VSPI); SPIClass* spiClass = new SPIClass(VSPI);
spiClass->begin(pin.nrf24_clk, pin.nrf24_miso, pin.nrf24_mosi, pin.nrf24_cs); spiClass->begin(pin.nrf24_clk, pin.nrf24_miso, pin.nrf24_mosi, pin.nrf24_cs);
Hoymiles.setMessageOutput(&MessageOutput); Hoymiles.setMessageOutput(&MessageOutput);
Hoymiles.init(spiClass, pin.nrf24_en, pin.nrf24_irq); 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); 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); Hoymiles.getRadio()->setDtuSerial(config.Dtu_Serial);
MessageOutput.println(F(" Setting poll interval... ")); MessageOutput.println(" Setting poll interval... ");
Hoymiles.setPollInterval(config.Dtu_PollInterval); Hoymiles.setPollInterval(config.Dtu_PollInterval);
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) { for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
if (config.Inverter[i].Serial > 0) { if (config.Inverter[i].Serial > 0) {
MessageOutput.print(F(" Adding inverter: ")); MessageOutput.print(" Adding inverter: ");
MessageOutput.print(config.Inverter[i].Serial, HEX); MessageOutput.print(config.Inverter[i].Serial, HEX);
MessageOutput.print(F(" - ")); MessageOutput.print(" - ");
MessageOutput.print(config.Inverter[i].Name); MessageOutput.print(config.Inverter[i].Name);
auto inv = Hoymiles.addInverter( auto inv = Hoymiles.addInverter(
config.Inverter[i].Name, 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); 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 { } else {
MessageOutput.println(F("Invalid pin config")); MessageOutput.println("Invalid pin config");
} }
} }

View File

@ -121,26 +121,26 @@ void MqttHandleHassClass::publishField(std::shared_ptr<InverterAbstract> inv, Ch
} }
DynamicJsonDocument root(1024); DynamicJsonDocument root(1024);
root[F("name")] = name; root["name"] = name;
root[F("stat_t")] = stateTopic; root["stat_t"] = stateTopic;
root[F("uniq_id")] = serial + "_ch" + chanNum + "_" + fieldName; root["uniq_id"] = serial + "_ch" + chanNum + "_" + fieldName;
String unit_of_measure = inv->Statistics()->getChannelFieldUnit(type, channel, fieldType.fieldId); String unit_of_measure = inv->Statistics()->getChannelFieldUnit(type, channel, fieldType.fieldId);
if (unit_of_measure != "") { if (unit_of_measure != "") {
root[F("unit_of_meas")] = unit_of_measure; root["unit_of_meas"] = unit_of_measure;
} }
JsonObject deviceObj = root.createNestedObject("dev"); JsonObject deviceObj = root.createNestedObject("dev");
createDeviceInfo(deviceObj, inv); createDeviceInfo(deviceObj, inv);
if (Configuration.get().Mqtt_Hass_Expire) { 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) { if (devCls != 0) {
root[F("dev_cla")] = devCls; root["dev_cla"] = devCls;
} }
if (stateCls != 0) { if (stateCls != 0) {
root[F("stat_cla")] = stateCls; root["stat_cla"] = stateCls;
} }
char buffer[512]; char buffer[512];
@ -166,17 +166,17 @@ void MqttHandleHassClass::publishInverterButton(std::shared_ptr<InverterAbstract
String cmdTopic = MqttSettings.getPrefix() + serial + "/" + subTopic; String cmdTopic = MqttSettings.getPrefix() + serial + "/" + subTopic;
DynamicJsonDocument root(1024); DynamicJsonDocument root(1024);
root[F("name")] = String(inv->name()) + " " + caption; root["name"] = String(inv->name()) + " " + caption;
root[F("uniq_id")] = serial + "_" + buttonId; root["uniq_id"] = serial + "_" + buttonId;
if (strcmp(icon, "")) { if (strcmp(icon, "")) {
root[F("ic")] = icon; root["ic"] = icon;
} }
if (strcmp(deviceClass, "")) { if (strcmp(deviceClass, "")) {
root[F("dev_cla")] = deviceClass; root["dev_cla"] = deviceClass;
} }
root[F("ent_cat")] = category; root["ent_cat"] = category;
root[F("cmd_t")] = cmdTopic; root["cmd_t"] = cmdTopic;
root[F("payload_press")] = payload; root["payload_press"] = payload;
JsonObject deviceObj = root.createNestedObject("dev"); JsonObject deviceObj = root.createNestedObject("dev");
createDeviceInfo(deviceObj, inv); createDeviceInfo(deviceObj, inv);
@ -205,17 +205,17 @@ void MqttHandleHassClass::publishInverterNumber(
String statTopic = MqttSettings.getPrefix() + serial + "/" + stateTopic; String statTopic = MqttSettings.getPrefix() + serial + "/" + stateTopic;
DynamicJsonDocument root(1024); DynamicJsonDocument root(1024);
root[F("name")] = String(inv->name()) + " " + caption; root["name"] = String(inv->name()) + " " + caption;
root[F("uniq_id")] = serial + "_" + buttonId; root["uniq_id"] = serial + "_" + buttonId;
if (strcmp(icon, "")) { if (strcmp(icon, "")) {
root[F("ic")] = icon; root["ic"] = icon;
} }
root[F("ent_cat")] = category; root["ent_cat"] = category;
root[F("cmd_t")] = cmdTopic; root["cmd_t"] = cmdTopic;
root[F("stat_t")] = statTopic; root["stat_t"] = statTopic;
root[F("unit_of_meas")] = unitOfMeasure; root["unit_of_meas"] = unitOfMeasure;
root[F("min")] = min; root["min"] = min;
root[F("max")] = max; root["max"] = max;
JsonObject deviceObj = root.createNestedObject("dev"); JsonObject deviceObj = root.createNestedObject("dev");
createDeviceInfo(deviceObj, inv); createDeviceInfo(deviceObj, inv);
@ -240,11 +240,11 @@ void MqttHandleHassClass::publishInverterBinarySensor(std::shared_ptr<InverterAb
String statTopic = MqttSettings.getPrefix() + serial + "/" + subTopic; String statTopic = MqttSettings.getPrefix() + serial + "/" + subTopic;
DynamicJsonDocument root(1024); DynamicJsonDocument root(1024);
root[F("name")] = String(inv->name()) + " " + caption; root["name"] = String(inv->name()) + " " + caption;
root[F("uniq_id")] = serial + "_" + sensorId; root["uniq_id"] = serial + "_" + sensorId;
root[F("stat_t")] = statTopic; root["stat_t"] = statTopic;
root[F("pl_on")] = payload_on; root["pl_on"] = payload_on;
root[F("pl_off")] = payload_off; root["pl_off"] = payload_off;
JsonObject deviceObj = root.createNestedObject("dev"); JsonObject deviceObj = root.createNestedObject("dev");
createDeviceInfo(deviceObj, inv); createDeviceInfo(deviceObj, inv);
@ -256,12 +256,12 @@ void MqttHandleHassClass::publishInverterBinarySensor(std::shared_ptr<InverterAb
void MqttHandleHassClass::createDeviceInfo(JsonObject& object, std::shared_ptr<InverterAbstract> inv) void MqttHandleHassClass::createDeviceInfo(JsonObject& object, std::shared_ptr<InverterAbstract> inv)
{ {
object[F("name")] = inv->name(); object["name"] = inv->name();
object[F("ids")] = inv->serialString(); object["ids"] = inv->serialString();
object[F("cu")] = String(F("http://")) + NetworkSettings.localIP().toString(); object["cu"] = String("http://") + NetworkSettings.localIP().toString();
object[F("mf")] = F("OpenDTU"); object["mf"] = "OpenDTU";
object[F("mdl")] = inv->typeName(); object["mdl"] = inv->typeName();
object[F("sw")] = AUTO_GIT_HASH; object["sw"] = AUTO_GIT_HASH;
} }
void MqttHandleHassClass::publish(const String& subtopic, const String& payload) void MqttHandleHassClass::publish(const String& subtopic, const String& payload)

View File

@ -185,7 +185,7 @@ void MqttHandleInverterClass::onMqttMessage(const espMqttClientTypes::MessagePro
auto inv = Hoymiles.getInverterBySerial(serial); auto inv = Hoymiles.getInverterBySerial(serial);
if (inv == nullptr) { if (inv == nullptr) {
MessageOutput.println(F("Inverter not found")); MessageOutput.println("Inverter not found");
return; return;
} }

View File

@ -14,11 +14,11 @@ void MqttSettingsClass::NetworkEvent(network_event event)
{ {
switch (event) { switch (event) {
case network_event::NETWORK_GOT_IP: case network_event::NETWORK_GOT_IP:
MessageOutput.println(F("Network connected")); MessageOutput.println("Network connected");
performConnect(); performConnect();
break; break;
case network_event::NETWORK_DISCONNECTED: 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 mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
break; break;
default: default:
@ -28,7 +28,7 @@ void MqttSettingsClass::NetworkEvent(network_event event)
void MqttSettingsClass::onMqttConnect(bool sessionPresent) void MqttSettingsClass::onMqttConnect(bool sessionPresent)
{ {
MessageOutput.println(F("Connected to MQTT.")); MessageOutput.println("Connected to MQTT.");
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
publish(config.Mqtt_LwtTopic, config.Mqtt_LwtValue_Online); publish(config.Mqtt_LwtTopic, config.Mqtt_LwtValue_Online);
@ -51,30 +51,30 @@ void MqttSettingsClass::unsubscribe(const String& topic)
void MqttSettingsClass::onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) 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) { switch (reason) {
case espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED: case espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED:
MessageOutput.println(F("TCP_DISCONNECTED")); MessageOutput.println("TCP_DISCONNECTED");
break; break;
case espMqttClientTypes::DisconnectReason::MQTT_UNACCEPTABLE_PROTOCOL_VERSION: case espMqttClientTypes::DisconnectReason::MQTT_UNACCEPTABLE_PROTOCOL_VERSION:
MessageOutput.println(F("MQTT_UNACCEPTABLE_PROTOCOL_VERSION")); MessageOutput.println("MQTT_UNACCEPTABLE_PROTOCOL_VERSION");
break; break;
case espMqttClientTypes::DisconnectReason::MQTT_IDENTIFIER_REJECTED: case espMqttClientTypes::DisconnectReason::MQTT_IDENTIFIER_REJECTED:
MessageOutput.println(F("MQTT_IDENTIFIER_REJECTED")); MessageOutput.println("MQTT_IDENTIFIER_REJECTED");
break; break;
case espMqttClientTypes::DisconnectReason::MQTT_SERVER_UNAVAILABLE: case espMqttClientTypes::DisconnectReason::MQTT_SERVER_UNAVAILABLE:
MessageOutput.println(F("MQTT_SERVER_UNAVAILABLE")); MessageOutput.println("MQTT_SERVER_UNAVAILABLE");
break; break;
case espMqttClientTypes::DisconnectReason::MQTT_MALFORMED_CREDENTIALS: case espMqttClientTypes::DisconnectReason::MQTT_MALFORMED_CREDENTIALS:
MessageOutput.println(F("MQTT_MALFORMED_CREDENTIALS")); MessageOutput.println("MQTT_MALFORMED_CREDENTIALS");
break; break;
case espMqttClientTypes::DisconnectReason::MQTT_NOT_AUTHORIZED: case espMqttClientTypes::DisconnectReason::MQTT_NOT_AUTHORIZED:
MessageOutput.println(F("MQTT_NOT_AUTHORIZED")); MessageOutput.println("MQTT_NOT_AUTHORIZED");
break; break;
default: default:
MessageOutput.println(F("Unknown")); MessageOutput.println("Unknown");
} }
mqttReconnectTimer.once( mqttReconnectTimer.once(
2, +[](MqttSettingsClass* instance) { instance->performConnect(); }, this); 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) 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); MessageOutput.println(topic);
_mqttSubscribeParser.handle_message(properties, topic, payload, len, index, total); _mqttSubscribeParser.handle_message(properties, topic, payload, len, index, total);
@ -97,7 +97,7 @@ void MqttSettingsClass::performConnect()
using std::placeholders::_4; using std::placeholders::_4;
using std::placeholders::_5; using std::placeholders::_5;
using std::placeholders::_6; using std::placeholders::_6;
MessageOutput.println(F("Connecting to MQTT...")); MessageOutput.println("Connecting to MQTT...");
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
willTopic = getPrefix() + config.Mqtt_LwtTopic; willTopic = getPrefix() + config.Mqtt_LwtTopic;
clientId = NetworkSettings.getApName(); clientId = NetworkSettings.getApName();

View File

@ -29,19 +29,19 @@ void NetworkSettingsClass::NetworkEvent(WiFiEvent_t event)
{ {
switch (event) { switch (event) {
case ARDUINO_EVENT_ETH_START: case ARDUINO_EVENT_ETH_START:
MessageOutput.println(F("ETH start")); MessageOutput.println("ETH start");
if (_networkMode == network_mode::Ethernet) { if (_networkMode == network_mode::Ethernet) {
raiseEvent(network_event::NETWORK_START); raiseEvent(network_event::NETWORK_START);
} }
break; break;
case ARDUINO_EVENT_ETH_STOP: case ARDUINO_EVENT_ETH_STOP:
MessageOutput.println(F("ETH stop")); MessageOutput.println("ETH stop");
if (_networkMode == network_mode::Ethernet) { if (_networkMode == network_mode::Ethernet) {
raiseEvent(network_event::NETWORK_STOP); raiseEvent(network_event::NETWORK_STOP);
} }
break; break;
case ARDUINO_EVENT_ETH_CONNECTED: case ARDUINO_EVENT_ETH_CONNECTED:
MessageOutput.println(F("ETH connected")); MessageOutput.println("ETH connected");
_ethConnected = true; _ethConnected = true;
raiseEvent(network_event::NETWORK_CONNECTED); raiseEvent(network_event::NETWORK_CONNECTED);
break; break;
@ -52,22 +52,22 @@ void NetworkSettingsClass::NetworkEvent(WiFiEvent_t event)
} }
break; break;
case ARDUINO_EVENT_ETH_DISCONNECTED: case ARDUINO_EVENT_ETH_DISCONNECTED:
MessageOutput.println(F("ETH disconnected")); MessageOutput.println("ETH disconnected");
_ethConnected = false; _ethConnected = false;
if (_networkMode == network_mode::Ethernet) { if (_networkMode == network_mode::Ethernet) {
raiseEvent(network_event::NETWORK_DISCONNECTED); raiseEvent(network_event::NETWORK_DISCONNECTED);
} }
break; break;
case ARDUINO_EVENT_WIFI_STA_CONNECTED: case ARDUINO_EVENT_WIFI_STA_CONNECTED:
MessageOutput.println(F("WiFi connected")); MessageOutput.println("WiFi connected");
if (_networkMode == network_mode::WiFi) { if (_networkMode == network_mode::WiFi) {
raiseEvent(network_event::NETWORK_CONNECTED); raiseEvent(network_event::NETWORK_CONNECTED);
} }
break; break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
MessageOutput.println(F("WiFi disconnected")); MessageOutput.println("WiFi disconnected");
if (_networkMode == network_mode::WiFi) { if (_networkMode == network_mode::WiFi) {
MessageOutput.println(F("Try reconnecting")); MessageOutput.println("Try reconnecting");
WiFi.reconnect(); WiFi.reconnect();
raiseEvent(network_event::NETWORK_DISCONNECTED); raiseEvent(network_event::NETWORK_DISCONNECTED);
} }
@ -154,7 +154,7 @@ void NetworkSettingsClass::loop()
if (_ethConnected) { if (_ethConnected) {
if (_networkMode != network_mode::Ethernet) { if (_networkMode != network_mode::Ethernet) {
// Do stuff when switching to Ethernet mode // Do stuff when switching to Ethernet mode
MessageOutput.println(F("Switch to Ethernet mode")); MessageOutput.println("Switch to Ethernet mode");
_networkMode = network_mode::Ethernet; _networkMode = network_mode::Ethernet;
WiFi.mode(WIFI_MODE_NULL); WiFi.mode(WIFI_MODE_NULL);
setStaticIp(); setStaticIp();
@ -163,7 +163,7 @@ void NetworkSettingsClass::loop()
} else } else
if (_networkMode != network_mode::WiFi) { if (_networkMode != network_mode::WiFi) {
// Do stuff when switching to Ethernet mode // Do stuff when switching to Ethernet mode
MessageOutput.println(F("Switch to WiFi mode")); MessageOutput.println("Switch to WiFi mode");
_networkMode = network_mode::WiFi; _networkMode = network_mode::WiFi;
enableAdminMode(); enableAdminMode();
applyConfig(); applyConfig();
@ -184,7 +184,7 @@ void NetworkSettingsClass::loop()
// seconds, disable the internal Access Point // seconds, disable the internal Access Point
if (adminTimeoutCounter > ADMIN_TIMEOUT) { if (adminTimeoutCounter > ADMIN_TIMEOUT) {
adminEnabled = false; adminEnabled = false;
MessageOutput.println(F("Admin mode disabled")); MessageOutput.println("Admin mode disabled");
setupMode(); setupMode();
} }
// It's nearly not possible to use the internal AP if the // It's nearly not possible to use the internal AP if the
@ -195,16 +195,16 @@ void NetworkSettingsClass::loop()
connectRedoTimer = 0; connectRedoTimer = 0;
} else { } else {
if (connectTimeoutTimer > WIFI_RECONNECT_TIMEOUT && !forceDisconnection) { if (connectTimeoutTimer > WIFI_RECONNECT_TIMEOUT && !forceDisconnection) {
MessageOutput.print(F("Disable search for AP... ")); MessageOutput.print("Disable search for AP... ");
WiFi.mode(WIFI_AP); WiFi.mode(WIFI_AP);
MessageOutput.println(F("done")); MessageOutput.println("done");
connectRedoTimer = 0; connectRedoTimer = 0;
forceDisconnection = true; forceDisconnection = true;
} }
if (connectRedoTimer > WIFI_RECONNECT_REDO_TIMEOUT && forceDisconnection) { 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); WiFi.mode(WIFI_AP_STA);
MessageOutput.println(F("done")); MessageOutput.println("done");
applyConfig(); applyConfig();
connectTimeoutTimer = 0; connectTimeoutTimer = 0;
forceDisconnection = false; forceDisconnection = false;
@ -222,28 +222,28 @@ void NetworkSettingsClass::applyConfig()
if (!strcmp(Configuration.get().WiFi_Ssid, "")) { if (!strcmp(Configuration.get().WiFi_Ssid, "")) {
return; 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)) { 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( WiFi.begin(
Configuration.get().WiFi_Ssid, Configuration.get().WiFi_Ssid,
Configuration.get().WiFi_Password); Configuration.get().WiFi_Password);
} else { } else {
MessageOutput.print(F("existing credentials... ")); MessageOutput.print("existing credentials... ");
WiFi.begin(); WiFi.begin();
} }
MessageOutput.println(F("done")); MessageOutput.println("done");
setStaticIp(); setStaticIp();
} }
void NetworkSettingsClass::setHostname() void NetworkSettingsClass::setHostname()
{ {
MessageOutput.print(F("Setting Hostname... ")); MessageOutput.print("Setting Hostname... ");
if (_networkMode == network_mode::WiFi) { if (_networkMode == network_mode::WiFi) {
if (WiFi.hostname(getHostname())) { if (WiFi.hostname(getHostname())) {
MessageOutput.println(F("done")); MessageOutput.println("done");
} else { } else {
MessageOutput.println(F("failed")); MessageOutput.println("failed");
} }
// Evil bad hack to get the hostname set up correctly // Evil bad hack to get the hostname set up correctly
@ -253,9 +253,9 @@ void NetworkSettingsClass::setHostname()
} }
else if (_networkMode == network_mode::Ethernet) { else if (_networkMode == network_mode::Ethernet) {
if (ETH.setHostname(getHostname().c_str())) { if (ETH.setHostname(getHostname().c_str())) {
MessageOutput.println(F("done")); MessageOutput.println("done");
} else { } else {
MessageOutput.println(F("failed")); MessageOutput.println("failed");
} }
} }
} }
@ -264,34 +264,34 @@ void NetworkSettingsClass::setStaticIp()
{ {
if (_networkMode == network_mode::WiFi) { if (_networkMode == network_mode::WiFi) {
if (Configuration.get().WiFi_Dhcp) { 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); WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
MessageOutput.println(F("done")); MessageOutput.println("done");
} else { } else {
MessageOutput.print(F("Configuring WiFi STA static IP... ")); MessageOutput.print("Configuring WiFi STA static IP... ");
WiFi.config( WiFi.config(
IPAddress(Configuration.get().WiFi_Ip), IPAddress(Configuration.get().WiFi_Ip),
IPAddress(Configuration.get().WiFi_Gateway), IPAddress(Configuration.get().WiFi_Gateway),
IPAddress(Configuration.get().WiFi_Netmask), IPAddress(Configuration.get().WiFi_Netmask),
IPAddress(Configuration.get().WiFi_Dns1), IPAddress(Configuration.get().WiFi_Dns1),
IPAddress(Configuration.get().WiFi_Dns2)); IPAddress(Configuration.get().WiFi_Dns2));
MessageOutput.println(F("done")); MessageOutput.println("done");
} }
} }
else if (_networkMode == network_mode::Ethernet) { else if (_networkMode == network_mode::Ethernet) {
if (Configuration.get().WiFi_Dhcp) { 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); ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
MessageOutput.println(F("done")); MessageOutput.println("done");
} else { } else {
MessageOutput.print(F("Configuring Ethernet static IP... ")); MessageOutput.print("Configuring Ethernet static IP... ");
ETH.config( ETH.config(
IPAddress(Configuration.get().WiFi_Ip), IPAddress(Configuration.get().WiFi_Ip),
IPAddress(Configuration.get().WiFi_Gateway), IPAddress(Configuration.get().WiFi_Gateway),
IPAddress(Configuration.get().WiFi_Netmask), IPAddress(Configuration.get().WiFi_Netmask),
IPAddress(Configuration.get().WiFi_Dns1), IPAddress(Configuration.get().WiFi_Dns1),
IPAddress(Configuration.get().WiFi_Dns2)); IPAddress(Configuration.get().WiFi_Dns2));
MessageOutput.println(F("done")); MessageOutput.println("done");
} }
} }
} }

View File

@ -92,7 +92,7 @@ bool PinMappingClass::init(const String& deviceMapping)
// Deserialize the JSON document // Deserialize the JSON document
DeserializationError error = deserializeJson(doc, f); DeserializationError error = deserializeJson(doc, f);
if (error) { 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++) { for (uint8_t i = 0; i < doc.size(); i++) {

View File

@ -91,7 +91,7 @@ bool WebApiClass::checkCredentials(AsyncWebServerRequest* request)
// WebAPI should set the X-Requested-With to prevent browser internal auth dialogs // WebAPI should set the X-Requested-With to prevent browser internal auth dialogs
if (!request->hasHeader("X-Requested-With")) { 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); request->send(r);

View File

@ -59,11 +59,11 @@ void WebApiConfigClass::onConfigDelete(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -72,8 +72,8 @@ void WebApiConfigClass::onConfigDelete(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > 1024) { if (json.length() > 1024) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -83,32 +83,32 @@ void WebApiConfigClass::onConfigDelete(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (!(root.containsKey("delete"))) { if (!(root.containsKey("delete"))) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("delete")].as<bool>() == false) { if (root["delete"].as<bool>() == false) {
retMsg[F("message")] = F("Not deleted anything!"); retMsg["message"] = "Not deleted anything!";
retMsg[F("code")] = WebApiError::ConfigNotDeleted; retMsg["code"] = WebApiError::ConfigNotDeleted;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Configuration resettet. Rebooting now..."); retMsg["message"] = "Configuration resettet. Rebooting now...";
retMsg[F("code")] = WebApiError::ConfigSuccess; retMsg["code"] = WebApiError::ConfigSuccess;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -125,7 +125,7 @@ void WebApiConfigClass::onConfigListGet(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
JsonArray data = root.createNestedArray(F("configs")); JsonArray data = root.createNestedArray("configs");
File rootfs = LittleFS.open("/"); File rootfs = LittleFS.open("/");
File file = rootfs.openNextFile(); File file = rootfs.openNextFile();

View File

@ -37,37 +37,37 @@ void WebApiDeviceClass::onDeviceAdminGet(AsyncWebServerRequest* request)
const PinMapping_t& pin = PinMapping.get(); const PinMapping_t& pin = PinMapping.get();
JsonObject curPin = root.createNestedObject("curPin"); JsonObject curPin = root.createNestedObject("curPin");
curPin[F("name")] = config.Dev_PinMapping; curPin["name"] = config.Dev_PinMapping;
JsonObject nrfPinObj = curPin.createNestedObject("nrf24"); JsonObject nrfPinObj = curPin.createNestedObject("nrf24");
nrfPinObj[F("clk")] = pin.nrf24_clk; nrfPinObj["clk"] = pin.nrf24_clk;
nrfPinObj[F("cs")] = pin.nrf24_cs; nrfPinObj["cs"] = pin.nrf24_cs;
nrfPinObj[F("en")] = pin.nrf24_en; nrfPinObj["en"] = pin.nrf24_en;
nrfPinObj[F("irq")] = pin.nrf24_irq; nrfPinObj["irq"] = pin.nrf24_irq;
nrfPinObj[F("miso")] = pin.nrf24_miso; nrfPinObj["miso"] = pin.nrf24_miso;
nrfPinObj[F("mosi")] = pin.nrf24_mosi; nrfPinObj["mosi"] = pin.nrf24_mosi;
JsonObject ethPinObj = curPin.createNestedObject("eth"); JsonObject ethPinObj = curPin.createNestedObject("eth");
ethPinObj[F("enabled")] = pin.eth_enabled; ethPinObj["enabled"] = pin.eth_enabled;
ethPinObj[F("phy_addr")] = pin.eth_phy_addr; ethPinObj["phy_addr"] = pin.eth_phy_addr;
ethPinObj[F("power")] = pin.eth_power; ethPinObj["power"] = pin.eth_power;
ethPinObj[F("mdc")] = pin.eth_mdc; ethPinObj["mdc"] = pin.eth_mdc;
ethPinObj[F("mdio")] = pin.eth_mdio; ethPinObj["mdio"] = pin.eth_mdio;
ethPinObj[F("type")] = pin.eth_type; ethPinObj["type"] = pin.eth_type;
ethPinObj[F("clk_mode")] = pin.eth_clk_mode; ethPinObj["clk_mode"] = pin.eth_clk_mode;
JsonObject displayPinObj = curPin.createNestedObject("display"); JsonObject displayPinObj = curPin.createNestedObject("display");
displayPinObj[F("type")] = pin.display_type; displayPinObj["type"] = pin.display_type;
displayPinObj[F("data")] = pin.display_data; displayPinObj["data"] = pin.display_data;
displayPinObj[F("clk")] = pin.display_clk; displayPinObj["clk"] = pin.display_clk;
displayPinObj[F("cs")] = pin.display_cs; displayPinObj["cs"] = pin.display_cs;
displayPinObj[F("reset")] = pin.display_reset; displayPinObj["reset"] = pin.display_reset;
JsonObject display = root.createNestedObject("display"); JsonObject display = root.createNestedObject("display");
display[F("rotation")] = config.Display_Rotation; display["rotation"] = config.Display_Rotation;
display[F("power_safe")] = config.Display_PowerSafe; display["power_safe"] = config.Display_PowerSafe;
display[F("screensaver")] = config.Display_ScreenSaver; display["screensaver"] = config.Display_ScreenSaver;
display[F("contrast")] = config.Display_Contrast; display["contrast"] = config.Display_Contrast;
JsonObject victronPinObj = curPin.createNestedObject("victron"); JsonObject victronPinObj = curPin.createNestedObject("victron");
victronPinObj[F("rx")] = pin.victron_rx; victronPinObj[F("rx")] = pin.victron_rx;
@ -97,11 +97,11 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE); AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -110,8 +110,8 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > MQTT_JSON_DOC_SIZE) { if (json.length() > MQTT_JSON_DOC_SIZE) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -121,38 +121,38 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (!(root.containsKey("curPin") || root.containsKey("display"))) { if (!(root.containsKey("curPin") || root.containsKey("display"))) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("curPin")][F("name")].as<String>().length() == 0 || root[F("curPin")][F("name")].as<String>().length() > 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[F("message")] = F("Pin mapping must between 1 and " STR(DEV_MAX_MAPPING_NAME_STRLEN) " characters long!"); retMsg["message"] = "Pin mapping must between 1 and " STR(DEV_MAX_MAPPING_NAME_STRLEN) " characters long!";
retMsg[F("code")] = WebApiError::HardwarePinMappingLength; retMsg["code"] = WebApiError::HardwarePinMappingLength;
retMsg[F("param")][F("max")] = DEV_MAX_MAPPING_NAME_STRLEN; retMsg["param"]["max"] = DEV_MAX_MAPPING_NAME_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
CONFIG_T& config = Configuration.get(); 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)); strlcpy(config.Dev_PinMapping, root["curPin"]["name"].as<String>().c_str(), sizeof(config.Dev_PinMapping));
config.Display_Rotation = root[F("display")][F("rotation")].as<uint8_t>(); config.Display_Rotation = root["display"]["rotation"].as<uint8_t>();
config.Display_PowerSafe = root[F("display")][F("power_safe")].as<bool>(); config.Display_PowerSafe = root["display"]["power_safe"].as<bool>();
config.Display_ScreenSaver = root[F("display")][F("screensaver")].as<bool>(); config.Display_ScreenSaver = root["display"]["screensaver"].as<bool>();
config.Display_Contrast = root[F("display")][F("contrast")].as<uint8_t>(); config.Display_Contrast = root["display"]["contrast"].as<uint8_t>();
Display.setOrientation(config.Display_Rotation); Display.setOrientation(config.Display_Rotation);
Display.enablePowerSafe = config.Display_PowerSafe; Display.enablePowerSafe = config.Display_PowerSafe;
@ -161,9 +161,9 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
Configuration.write(); Configuration.write();
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Settings saved!"); retMsg["message"] = "Settings saved!";
retMsg[F("code")] = WebApiError::GenericSuccess; retMsg["code"] = WebApiError::GenericSuccess;
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@ -34,18 +34,18 @@ void WebApiDevInfoClass::onDevInfoStatus(AsyncWebServerRequest* request)
auto inv = Hoymiles.getInverterByPos(i); auto inv = Hoymiles.getInverterByPos(i);
JsonObject devInfoObj = root[inv->serialString()].createNestedObject(); JsonObject devInfoObj = root[inv->serialString()].createNestedObject();
devInfoObj[F("valid_data")] = inv->DevInfo()->getLastUpdate() > 0; devInfoObj["valid_data"] = inv->DevInfo()->getLastUpdate() > 0;
devInfoObj[F("fw_bootloader_version")] = inv->DevInfo()->getFwBootloaderVersion(); devInfoObj["fw_bootloader_version"] = inv->DevInfo()->getFwBootloaderVersion();
devInfoObj[F("fw_build_version")] = inv->DevInfo()->getFwBuildVersion(); devInfoObj["fw_build_version"] = inv->DevInfo()->getFwBuildVersion();
devInfoObj[F("hw_part_number")] = inv->DevInfo()->getHwPartNumber(); devInfoObj["hw_part_number"] = inv->DevInfo()->getHwPartNumber();
devInfoObj[F("hw_version")] = inv->DevInfo()->getHwVersion(); devInfoObj["hw_version"] = inv->DevInfo()->getHwVersion();
devInfoObj[F("hw_model_name")] = inv->DevInfo()->getHwModelName(); devInfoObj["hw_model_name"] = inv->DevInfo()->getHwModelName();
devInfoObj[F("max_power")] = inv->DevInfo()->getMaxPower(); devInfoObj["max_power"] = inv->DevInfo()->getMaxPower();
char timebuffer[32]; char timebuffer[32];
const time_t t = inv->DevInfo()->getFwBuildDateTime(); const time_t t = inv->DevInfo()->getFwBuildDateTime();
std::strftime(timebuffer, sizeof(timebuffer), "%Y-%m-%d %H:%M:%S", gmtime(&t)); 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(); response->setLength();

View File

@ -38,9 +38,9 @@ void WebApiDtuClass::onDtuAdminGet(AsyncWebServerRequest* request)
snprintf(buffer, sizeof(buffer), "%0x%08x", snprintf(buffer, sizeof(buffer), "%0x%08x",
((uint32_t)((config.Dtu_Serial >> 32) & 0xFFFFFFFF)), ((uint32_t)((config.Dtu_Serial >> 32) & 0xFFFFFFFF)),
((uint32_t)(config.Dtu_Serial & 0xFFFFFFFF))); ((uint32_t)(config.Dtu_Serial & 0xFFFFFFFF)));
root[F("dtu_serial")] = buffer; root["dtu_serial"] = buffer;
root[F("dtu_pollinterval")] = config.Dtu_PollInterval; root["dtu_pollinterval"] = config.Dtu_PollInterval;
root[F("dtu_palevel")] = config.Dtu_PaLevel; root["dtu_palevel"] = config.Dtu_PaLevel;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -54,11 +54,11 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -67,8 +67,8 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > 1024) { if (json.length() > 1024) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -78,40 +78,40 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (!(root.containsKey("dtu_serial") && root.containsKey("dtu_pollinterval") && root.containsKey("dtu_palevel"))) { if (!(root.containsKey("dtu_serial") && root.containsKey("dtu_pollinterval") && root.containsKey("dtu_palevel"))) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("dtu_serial")].as<uint64_t>() == 0) { if (root["dtu_serial"].as<uint64_t>() == 0) {
retMsg[F("message")] = F("Serial cannot be zero!"); retMsg["message"] = "Serial cannot be zero!";
retMsg[F("code")] = WebApiError::DtuSerialZero; retMsg["code"] = WebApiError::DtuSerialZero;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("dtu_pollinterval")].as<uint32_t>() == 0) { if (root["dtu_pollinterval"].as<uint32_t>() == 0) {
retMsg[F("message")] = F("Poll interval must be greater zero!"); retMsg["message"] = "Poll interval must be greater zero!";
retMsg[F("code")] = WebApiError::DtuPollZero; retMsg["code"] = WebApiError::DtuPollZero;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("dtu_palevel")].as<uint8_t>() > 3) { if (root["dtu_palevel"].as<uint8_t>() > 3) {
retMsg[F("message")] = F("Invalid power level setting!"); retMsg["message"] = "Invalid power level setting!";
retMsg[F("code")] = WebApiError::DtuInvalidPowerLevel; retMsg["code"] = WebApiError::DtuInvalidPowerLevel;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -120,14 +120,14 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
CONFIG_T& config = Configuration.get(); CONFIG_T& config = Configuration.get();
// Interpret the string as a hex value and convert it to uint64_t // 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_Serial = strtoll(root["dtu_serial"].as<String>().c_str(), NULL, 16);
config.Dtu_PollInterval = root[F("dtu_pollinterval")].as<uint32_t>(); config.Dtu_PollInterval = root["dtu_pollinterval"].as<uint32_t>();
config.Dtu_PaLevel = root[F("dtu_palevel")].as<uint8_t>(); config.Dtu_PaLevel = root["dtu_palevel"].as<uint8_t>();
Configuration.write(); Configuration.write();
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Settings saved!"); retMsg["message"] = "Settings saved!";
retMsg[F("code")] = WebApiError::GenericSuccess; retMsg["code"] = WebApiError::GenericSuccess;
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@ -43,7 +43,7 @@ void WebApiEventlogClass::onEventlogStatus(AsyncWebServerRequest* request)
uint8_t logEntryCount = inv->EventLog()->getEntryCount(); uint8_t logEntryCount = inv->EventLog()->getEntryCount();
root[serial]["count"] = logEntryCount; 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++) { for (uint8_t logEntry = 0; logEntry < logEntryCount; logEntry++) {
JsonObject eventsObject = eventsArray.createNestedObject(); JsonObject eventsObject = eventsArray.createNestedObject();
@ -51,10 +51,10 @@ void WebApiEventlogClass::onEventlogStatus(AsyncWebServerRequest* request)
AlarmLogEntry_t entry; AlarmLogEntry_t entry;
inv->EventLog()->getLogEntry(logEntry, &entry); inv->EventLog()->getLogEntry(logEntry, &entry);
eventsObject[F("message_id")] = entry.MessageId; eventsObject["message_id"] = entry.MessageId;
eventsObject[F("message")] = entry.Message; eventsObject["message"] = entry.Message;
eventsObject[F("start_time")] = entry.StartTime; eventsObject["start_time"] = entry.StartTime;
eventsObject[F("end_time")] = entry.EndTime; eventsObject["end_time"] = entry.EndTime;
} }
} }

View File

@ -35,34 +35,34 @@ void WebApiInverterClass::onInverterList(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(false, 4096U); AsyncJsonResponse* response = new AsyncJsonResponse(false, 4096U);
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
JsonArray data = root.createNestedArray(F("inverter")); JsonArray data = root.createNestedArray("inverter");
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
for (uint8_t i = 0; i < INV_MAX_COUNT; i++) { for (uint8_t i = 0; i < INV_MAX_COUNT; i++) {
if (config.Inverter[i].Serial > 0) { if (config.Inverter[i].Serial > 0) {
JsonObject obj = data.createNestedObject(); JsonObject obj = data.createNestedObject();
obj[F("id")] = i; obj["id"] = i;
obj[F("name")] = String(config.Inverter[i].Name); obj["name"] = String(config.Inverter[i].Name);
// Inverter Serial is read as HEX // Inverter Serial is read as HEX
char buffer[sizeof(uint64_t) * 8 + 1]; char buffer[sizeof(uint64_t) * 8 + 1];
snprintf(buffer, sizeof(buffer), "%0x%08x", snprintf(buffer, sizeof(buffer), "%0x%08x",
((uint32_t)((config.Inverter[i].Serial >> 32) & 0xFFFFFFFF)), ((uint32_t)((config.Inverter[i].Serial >> 32) & 0xFFFFFFFF)),
((uint32_t)(config.Inverter[i].Serial & 0xFFFFFFFF))); ((uint32_t)(config.Inverter[i].Serial & 0xFFFFFFFF)));
obj[F("serial")] = buffer; obj["serial"] = buffer;
obj[F("poll_enable")] = config.Inverter[i].Poll_Enable; obj["poll_enable"] = config.Inverter[i].Poll_Enable;
obj[F("poll_enable_night")] = config.Inverter[i].Poll_Enable_Night; obj["poll_enable_night"] = config.Inverter[i].Poll_Enable_Night;
obj[F("command_enable")] = config.Inverter[i].Command_Enable; obj["command_enable"] = config.Inverter[i].Command_Enable;
obj[F("command_enable_night")] = config.Inverter[i].Command_Enable_Night; obj["command_enable_night"] = config.Inverter[i].Command_Enable_Night;
auto inv = Hoymiles.getInverterBySerial(config.Inverter[i].Serial); auto inv = Hoymiles.getInverterBySerial(config.Inverter[i].Serial);
uint8_t max_channels; uint8_t max_channels;
if (inv == nullptr) { if (inv == nullptr) {
obj[F("type")] = F("Unknown"); obj["type"] = "Unknown";
max_channels = INV_MAX_CHAN_COUNT; max_channels = INV_MAX_CHAN_COUNT;
} else { } else {
obj[F("type")] = inv->typeName(); obj["type"] = inv->typeName();
max_channels = inv->Statistics()->getChannelsByType(TYPE_DC).size(); max_channels = inv->Statistics()->getChannelsByType(TYPE_DC).size();
} }
@ -88,11 +88,11 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -101,8 +101,8 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > 1024) { if (json.length() > 1024) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -112,33 +112,33 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (!(root.containsKey("serial") && root.containsKey("name"))) { if (!(root.containsKey("serial") && root.containsKey("name"))) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("serial")].as<uint64_t>() == 0) { if (root["serial"].as<uint64_t>() == 0) {
retMsg[F("message")] = F("Serial must be a number > 0!"); retMsg["message"] = "Serial must be a number > 0!";
retMsg[F("code")] = WebApiError::InverterSerialZero; retMsg["code"] = WebApiError::InverterSerialZero;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("name")].as<String>().length() == 0 || root[F("name")].as<String>().length() > INV_MAX_NAME_STRLEN) { if (root["name"].as<String>().length() == 0 || root["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["message"] = "Name must between 1 and " STR(INV_MAX_NAME_STRLEN) " characters long!";
retMsg[F("code")] = WebApiError::InverterNameLength; retMsg["code"] = WebApiError::InverterNameLength;
retMsg[F("param")][F("max")] = INV_MAX_NAME_STRLEN; retMsg["param"]["max"] = INV_MAX_NAME_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -147,23 +147,23 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
INVERTER_CONFIG_T* inverter = Configuration.getFreeInverterSlot(); INVERTER_CONFIG_T* inverter = Configuration.getFreeInverterSlot();
if (!inverter) { if (!inverter) {
retMsg[F("message")] = F("Only " STR(INV_MAX_COUNT) " inverters are supported!"); retMsg["message"] = "Only " STR(INV_MAX_COUNT) " inverters are supported!";
retMsg[F("code")] = WebApiError::InverterCount; retMsg["code"] = WebApiError::InverterCount;
retMsg[F("param")][F("max")] = INV_MAX_COUNT; retMsg["param"]["max"] = INV_MAX_COUNT;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
// Interpret the string as a hex value and convert it to uint64_t // 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(); Configuration.write();
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Inverter created!"); retMsg["message"] = "Inverter created!";
retMsg[F("code")] = WebApiError::InverterAdded; retMsg["code"] = WebApiError::InverterAdded;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -187,11 +187,11 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -200,8 +200,8 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > 1024) { if (json.length() > 1024) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -211,82 +211,82 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (!(root.containsKey("id") && root.containsKey("serial") && root.containsKey("name") && root.containsKey("channel"))) { if (!(root.containsKey("id") && root.containsKey("serial") && root.containsKey("name") && root.containsKey("channel"))) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("id")].as<uint8_t>() > INV_MAX_COUNT - 1) { if (root["id"].as<uint8_t>() > INV_MAX_COUNT - 1) {
retMsg[F("message")] = F("Invalid ID specified!"); retMsg["message"] = "Invalid ID specified!";
retMsg[F("code")] = WebApiError::InverterInvalidId; retMsg["code"] = WebApiError::InverterInvalidId;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("serial")].as<uint64_t>() == 0) { if (root["serial"].as<uint64_t>() == 0) {
retMsg[F("message")] = F("Serial must be a number > 0!"); retMsg["message"] = "Serial must be a number > 0!";
retMsg[F("code")] = WebApiError::InverterSerialZero; retMsg["code"] = WebApiError::InverterSerialZero;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("name")].as<String>().length() == 0 || root[F("name")].as<String>().length() > INV_MAX_NAME_STRLEN) { if (root["name"].as<String>().length() == 0 || root["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["message"] = "Name must between 1 and " STR(INV_MAX_NAME_STRLEN) " characters long!";
retMsg[F("code")] = WebApiError::InverterNameLength; retMsg["code"] = WebApiError::InverterNameLength;
retMsg[F("param")][F("max")] = INV_MAX_NAME_STRLEN; retMsg["param"]["max"] = INV_MAX_NAME_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
JsonArray channelArray = root[F("channel")].as<JsonArray>(); JsonArray channelArray = root["channel"].as<JsonArray>();
if (channelArray.size() == 0 || channelArray.size() > INV_MAX_CHAN_COUNT) { if (channelArray.size() == 0 || channelArray.size() > INV_MAX_CHAN_COUNT) {
retMsg[F("message")] = F("Invalid amount of max channel setting given!"); retMsg["message"] = "Invalid amount of max channel setting given!";
retMsg[F("code")] = WebApiError::InverterInvalidMaxChannel; retMsg["code"] = WebApiError::InverterInvalidMaxChannel;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; 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; uint64_t old_serial = inverter.Serial;
// Interpret the string as a hex value and convert it to uint64_t // Interpret the string as a hex value and convert it to uint64_t
inverter.Serial = new_serial; 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; uint8_t arrayCount = 0;
for (JsonVariant channel : channelArray) { for (JsonVariant channel : channelArray) {
inverter.channel[arrayCount].MaxChannelPower = channel[F("max_power")].as<uint16_t>(); inverter.channel[arrayCount].MaxChannelPower = channel["max_power"].as<uint16_t>();
inverter.channel[arrayCount].YieldTotalOffset = channel[F("yield_total_offset")].as<float>(); inverter.channel[arrayCount].YieldTotalOffset = channel["yield_total_offset"].as<float>();
strncpy(inverter.channel[arrayCount].Name, channel[F("name")] | "", sizeof(inverter.channel[arrayCount].Name)); strncpy(inverter.channel[arrayCount].Name, channel["name"] | "", sizeof(inverter.channel[arrayCount].Name));
inverter.Poll_Enable = root[F("poll_enable")] | true; inverter.Poll_Enable = root["poll_enable"] | true;
inverter.Poll_Enable_Night = root[F("poll_enable_night")] | true; inverter.Poll_Enable_Night = root["poll_enable_night"] | true;
inverter.Command_Enable = root[F("command_enable")] | true; inverter.Command_Enable = root["command_enable"] | true;
inverter.Command_Enable_Night = root[F("command_enable_night")] | true; inverter.Command_Enable_Night = root["command_enable_night"] | true;
arrayCount++; arrayCount++;
} }
Configuration.write(); Configuration.write();
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("code")] = WebApiError::InverterChanged; retMsg["code"] = WebApiError::InverterChanged;
retMsg[F("message")] = F("Inverter changed!"); retMsg["message"] = "Inverter changed!";
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -325,11 +325,11 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -338,8 +338,8 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > 1024) { if (json.length() > 1024) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -349,30 +349,30 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (!(root.containsKey("id"))) { if (!(root.containsKey("id"))) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("id")].as<uint8_t>() > INV_MAX_COUNT - 1) { if (root["id"].as<uint8_t>() > INV_MAX_COUNT - 1) {
retMsg[F("message")] = F("Invalid ID specified!"); retMsg["message"] = "Invalid ID specified!";
retMsg[F("code")] = WebApiError::InverterInvalidId; retMsg["code"] = WebApiError::InverterInvalidId;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; 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]; INVERTER_CONFIG_T& inverter = Configuration.get().Inverter[inverter_id];
Hoymiles.removeInverterBySerial(inverter.Serial); Hoymiles.removeInverterBySerial(inverter.Serial);
@ -381,9 +381,9 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
strncpy(inverter.Name, "", sizeof(inverter.Name)); strncpy(inverter.Name, "", sizeof(inverter.Name));
Configuration.write(); Configuration.write();
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Inverter deleted!"); retMsg["message"] = "Inverter deleted!";
retMsg[F("code")] = WebApiError::InverterDeleted; retMsg["code"] = WebApiError::InverterDeleted;
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@ -63,11 +63,11 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -76,8 +76,8 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > 1024) { if (json.length() > 1024) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -87,8 +87,8 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -97,50 +97,50 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
if (!(root.containsKey("serial") if (!(root.containsKey("serial")
&& root.containsKey("limit_value") && root.containsKey("limit_value")
&& root.containsKey("limit_type"))) { && root.containsKey("limit_type"))) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("serial")].as<uint64_t>() == 0) { if (root["serial"].as<uint64_t>() == 0) {
retMsg[F("message")] = F("Serial must be a number > 0!"); retMsg["message"] = "Serial must be a number > 0!";
retMsg[F("code")] = WebApiError::LimitSerialZero; retMsg["code"] = WebApiError::LimitSerialZero;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("limit_value")].as<uint16_t>() == 0 || root[F("limit_value")].as<uint16_t>() > 1500) { if (root["limit_value"].as<uint16_t>() == 0 || root["limit_value"].as<uint16_t>() > 1500) {
retMsg[F("message")] = F("Limit must between 1 and 1500!"); retMsg["message"] = "Limit must between 1 and 1500!";
retMsg[F("code")] = WebApiError::LimitInvalidLimit; retMsg["code"] = WebApiError::LimitInvalidLimit;
retMsg[F("param")][F("max")] = 1500; retMsg["param"]["max"] = 1500;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (!((root[F("limit_type")].as<uint16_t>() == PowerLimitControlType::AbsolutNonPersistent) if (!((root["limit_type"].as<uint16_t>() == PowerLimitControlType::AbsolutNonPersistent)
|| (root[F("limit_type")].as<uint16_t>() == PowerLimitControlType::AbsolutPersistent) || (root["limit_type"].as<uint16_t>() == PowerLimitControlType::AbsolutPersistent)
|| (root[F("limit_type")].as<uint16_t>() == PowerLimitControlType::RelativNonPersistent) || (root["limit_type"].as<uint16_t>() == PowerLimitControlType::RelativNonPersistent)
|| (root[F("limit_type")].as<uint16_t>() == PowerLimitControlType::RelativPersistent))) { || (root["limit_type"].as<uint16_t>() == PowerLimitControlType::RelativPersistent))) {
retMsg[F("message")] = F("Invalid type specified!"); retMsg["message"] = "Invalid type specified!";
retMsg[F("code")] = WebApiError::LimitInvalidType; retMsg["code"] = WebApiError::LimitInvalidType;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; 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);
uint16_t limit = root[F("limit_value")].as<uint16_t>(); uint16_t limit = root["limit_value"].as<uint16_t>();
PowerLimitControlType type = root[F("limit_type")].as<PowerLimitControlType>(); PowerLimitControlType type = root["limit_type"].as<PowerLimitControlType>();
auto inv = Hoymiles.getInverterBySerial(serial); auto inv = Hoymiles.getInverterBySerial(serial);
if (inv == nullptr) { if (inv == nullptr) {
retMsg[F("message")] = F("Invalid inverter specified!"); retMsg["message"] = "Invalid inverter specified!";
retMsg[F("code")] = WebApiError::LimitInvalidInverter; retMsg["code"] = WebApiError::LimitInvalidInverter;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -148,9 +148,9 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)
inv->sendActivePowerControlRequest(Hoymiles.getRadio(), limit, type); inv->sendActivePowerControlRequest(Hoymiles.getRadio(), limit, type);
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Settings saved!"); retMsg["message"] = "Settings saved!";
retMsg[F("code")] = WebApiError::GenericSuccess; retMsg["code"] = WebApiError::GenericSuccess;
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@ -29,11 +29,11 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE); AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -42,8 +42,8 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > MQTT_JSON_DOC_SIZE) { if (json.length() > MQTT_JSON_DOC_SIZE) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -53,25 +53,25 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (!(root.containsKey("reboot"))) { if (!(root.containsKey("reboot"))) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("reboot")].as<bool>()) { if (root["reboot"].as<bool>()) {
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Reboot triggered!"); retMsg["message"] = "Reboot triggered!";
retMsg[F("code")] = WebApiError::MaintenanceRebootTriggered; retMsg["code"] = WebApiError::MaintenanceRebootTriggered;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -80,8 +80,8 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)
yield(); yield();
ESP.restart(); ESP.restart();
} else { } else {
retMsg[F("message")] = F("Reboot cancled!"); retMsg["message"] = "Reboot cancled!";
retMsg[F("code")] = WebApiError::MaintenanceRebootCancled; retMsg["code"] = WebApiError::MaintenanceRebootCancled;
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@ -39,22 +39,22 @@ void WebApiMqttClass::onMqttStatus(AsyncWebServerRequest* request)
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
root[F("mqtt_enabled")] = config.Mqtt_Enabled; root["mqtt_enabled"] = config.Mqtt_Enabled;
root[F("mqtt_hostname")] = config.Mqtt_Hostname; root["mqtt_hostname"] = config.Mqtt_Hostname;
root[F("mqtt_port")] = config.Mqtt_Port; root["mqtt_port"] = config.Mqtt_Port;
root[F("mqtt_username")] = config.Mqtt_Username; root["mqtt_username"] = config.Mqtt_Username;
root[F("mqtt_topic")] = config.Mqtt_Topic; root["mqtt_topic"] = config.Mqtt_Topic;
root[F("mqtt_connected")] = MqttSettings.getConnected(); root["mqtt_connected"] = MqttSettings.getConnected();
root[F("mqtt_retain")] = config.Mqtt_Retain; root["mqtt_retain"] = config.Mqtt_Retain;
root[F("mqtt_tls")] = config.Mqtt_Tls; root["mqtt_tls"] = config.Mqtt_Tls;
root[F("mqtt_root_ca_cert_info")] = getRootCaCertInfo(config.Mqtt_RootCaCert); root["mqtt_root_ca_cert_info"] = getRootCaCertInfo(config.Mqtt_RootCaCert);
root[F("mqtt_lwt_topic")] = String(config.Mqtt_Topic) + config.Mqtt_LwtTopic; root["mqtt_lwt_topic"] = String(config.Mqtt_Topic) + config.Mqtt_LwtTopic;
root[F("mqtt_publish_interval")] = config.Mqtt_PublishInterval; root["mqtt_publish_interval"] = config.Mqtt_PublishInterval;
root[F("mqtt_hass_enabled")] = config.Mqtt_Hass_Enabled; root["mqtt_hass_enabled"] = config.Mqtt_Hass_Enabled;
root[F("mqtt_hass_expire")] = config.Mqtt_Hass_Expire; root["mqtt_hass_expire"] = config.Mqtt_Hass_Expire;
root[F("mqtt_hass_retain")] = config.Mqtt_Hass_Retain; root["mqtt_hass_retain"] = config.Mqtt_Hass_Retain;
root[F("mqtt_hass_topic")] = config.Mqtt_Hass_Topic; root["mqtt_hass_topic"] = config.Mqtt_Hass_Topic;
root[F("mqtt_hass_individualpanels")] = config.Mqtt_Hass_IndividualPanels; root["mqtt_hass_individualpanels"] = config.Mqtt_Hass_IndividualPanels;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -70,24 +70,24 @@ void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request)
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
root[F("mqtt_enabled")] = config.Mqtt_Enabled; root["mqtt_enabled"] = config.Mqtt_Enabled;
root[F("mqtt_hostname")] = config.Mqtt_Hostname; root["mqtt_hostname"] = config.Mqtt_Hostname;
root[F("mqtt_port")] = config.Mqtt_Port; root["mqtt_port"] = config.Mqtt_Port;
root[F("mqtt_username")] = config.Mqtt_Username; root["mqtt_username"] = config.Mqtt_Username;
root[F("mqtt_password")] = config.Mqtt_Password; root["mqtt_password"] = config.Mqtt_Password;
root[F("mqtt_topic")] = config.Mqtt_Topic; root["mqtt_topic"] = config.Mqtt_Topic;
root[F("mqtt_retain")] = config.Mqtt_Retain; root["mqtt_retain"] = config.Mqtt_Retain;
root[F("mqtt_tls")] = config.Mqtt_Tls; root["mqtt_tls"] = config.Mqtt_Tls;
root[F("mqtt_root_ca_cert")] = config.Mqtt_RootCaCert; root["mqtt_root_ca_cert"] = config.Mqtt_RootCaCert;
root[F("mqtt_lwt_topic")] = config.Mqtt_LwtTopic; root["mqtt_lwt_topic"] = config.Mqtt_LwtTopic;
root[F("mqtt_lwt_online")] = config.Mqtt_LwtValue_Online; root["mqtt_lwt_online"] = config.Mqtt_LwtValue_Online;
root[F("mqtt_lwt_offline")] = config.Mqtt_LwtValue_Offline; root["mqtt_lwt_offline"] = config.Mqtt_LwtValue_Offline;
root[F("mqtt_publish_interval")] = config.Mqtt_PublishInterval; root["mqtt_publish_interval"] = config.Mqtt_PublishInterval;
root[F("mqtt_hass_enabled")] = config.Mqtt_Hass_Enabled; root["mqtt_hass_enabled"] = config.Mqtt_Hass_Enabled;
root[F("mqtt_hass_expire")] = config.Mqtt_Hass_Expire; root["mqtt_hass_expire"] = config.Mqtt_Hass_Expire;
root[F("mqtt_hass_retain")] = config.Mqtt_Hass_Retain; root["mqtt_hass_retain"] = config.Mqtt_Hass_Retain;
root[F("mqtt_hass_topic")] = config.Mqtt_Hass_Topic; root["mqtt_hass_topic"] = config.Mqtt_Hass_Topic;
root[F("mqtt_hass_individualpanels")] = config.Mqtt_Hass_IndividualPanels; root["mqtt_hass_individualpanels"] = config.Mqtt_Hass_IndividualPanels;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -101,11 +101,11 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE); AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -114,8 +114,8 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > MQTT_JSON_DOC_SIZE) { if (json.length() > MQTT_JSON_DOC_SIZE) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -125,8 +125,8 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -149,139 +149,139 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
&& root.containsKey("mqtt_hass_retain") && root.containsKey("mqtt_hass_retain")
&& root.containsKey("mqtt_hass_topic") && root.containsKey("mqtt_hass_topic")
&& root.containsKey("mqtt_hass_individualpanels"))) { && root.containsKey("mqtt_hass_individualpanels"))) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_enabled")].as<bool>()) { if (root["mqtt_enabled"].as<bool>()) {
if (root[F("mqtt_hostname")].as<String>().length() == 0 || root[F("mqtt_hostname")].as<String>().length() > MQTT_MAX_HOSTNAME_STRLEN) { if (root["mqtt_hostname"].as<String>().length() == 0 || root["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["message"] = "MqTT Server must between 1 and " STR(MQTT_MAX_HOSTNAME_STRLEN) " characters long!";
retMsg[F("code")] = WebApiError::MqttHostnameLength; retMsg["code"] = WebApiError::MqttHostnameLength;
retMsg[F("param")][F("max")] = MQTT_MAX_HOSTNAME_STRLEN; retMsg["param"]["max"] = MQTT_MAX_HOSTNAME_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_username")].as<String>().length() > MQTT_MAX_USERNAME_STRLEN) { if (root["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["message"] = "Username must not longer then " STR(MQTT_MAX_USERNAME_STRLEN) " characters!";
retMsg[F("code")] = WebApiError::MqttUsernameLength; retMsg["code"] = WebApiError::MqttUsernameLength;
retMsg[F("param")][F("max")] = MQTT_MAX_USERNAME_STRLEN; retMsg["param"]["max"] = MQTT_MAX_USERNAME_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_password")].as<String>().length() > MQTT_MAX_PASSWORD_STRLEN) { if (root["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["message"] = "Password must not longer then " STR(MQTT_MAX_PASSWORD_STRLEN) " characters!";
retMsg[F("code")] = WebApiError::MqttPasswordLength; retMsg["code"] = WebApiError::MqttPasswordLength;
retMsg[F("param")][F("max")] = MQTT_MAX_PASSWORD_STRLEN; retMsg["param"]["max"] = MQTT_MAX_PASSWORD_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_topic")].as<String>().length() > MQTT_MAX_TOPIC_STRLEN) { if (root["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["message"] = "Topic must not longer then " STR(MQTT_MAX_TOPIC_STRLEN) " characters!";
retMsg[F("code")] = WebApiError::MqttTopicLength; retMsg["code"] = WebApiError::MqttTopicLength;
retMsg[F("param")][F("max")] = MQTT_MAX_TOPIC_STRLEN; retMsg["param"]["max"] = MQTT_MAX_TOPIC_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_topic")].as<String>().indexOf(' ') != -1) { if (root["mqtt_topic"].as<String>().indexOf(' ') != -1) {
retMsg[F("message")] = F("Topic must not contain space characters!"); retMsg["message"] = "Topic must not contain space characters!";
retMsg[F("code")] = WebApiError::MqttTopicCharacter; retMsg["code"] = WebApiError::MqttTopicCharacter;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (!root[F("mqtt_topic")].as<String>().endsWith("/")) { if (!root["mqtt_topic"].as<String>().endsWith("/")) {
retMsg[F("message")] = F("Topic must end with slash (/)!"); retMsg["message"] = "Topic must end with slash (/)!";
retMsg[F("code")] = WebApiError::MqttTopicTrailingSlash; retMsg["code"] = WebApiError::MqttTopicTrailingSlash;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_port")].as<uint>() == 0 || root[F("mqtt_port")].as<uint>() > 65535) { if (root["mqtt_port"].as<uint>() == 0 || root["mqtt_port"].as<uint>() > 65535) {
retMsg[F("message")] = F("Port must be a number between 1 and 65535!"); retMsg["message"] = "Port must be a number between 1 and 65535!";
retMsg[F("code")] = WebApiError::MqttPort; retMsg["code"] = WebApiError::MqttPort;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_root_ca_cert")].as<String>().length() > MQTT_MAX_ROOT_CA_CERT_STRLEN) { if (root["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["message"] = "Certificate must not longer then " STR(MQTT_MAX_ROOT_CA_CERT_STRLEN) " characters!";
retMsg[F("code")] = WebApiError::MqttCertificateLength; retMsg["code"] = WebApiError::MqttCertificateLength;
retMsg[F("param")][F("max")] = MQTT_MAX_ROOT_CA_CERT_STRLEN; retMsg["param"]["max"] = MQTT_MAX_ROOT_CA_CERT_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_lwt_topic")].as<String>().length() > MQTT_MAX_TOPIC_STRLEN) { if (root["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["message"] = "LWT topic must not longer then " STR(MQTT_MAX_TOPIC_STRLEN) " characters!";
retMsg[F("code")] = WebApiError::MqttLwtTopicLength; retMsg["code"] = WebApiError::MqttLwtTopicLength;
retMsg[F("param")][F("max")] = MQTT_MAX_TOPIC_STRLEN; retMsg["param"]["max"] = MQTT_MAX_TOPIC_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_lwt_topic")].as<String>().indexOf(' ') != -1) { if (root["mqtt_lwt_topic"].as<String>().indexOf(' ') != -1) {
retMsg[F("message")] = F("LWT topic must not contain space characters!"); retMsg["message"] = "LWT topic must not contain space characters!";
retMsg[F("code")] = WebApiError::MqttLwtTopicCharacter; retMsg["code"] = WebApiError::MqttLwtTopicCharacter;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_lwt_online")].as<String>().length() > MQTT_MAX_LWTVALUE_STRLEN) { if (root["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["message"] = "LWT online value must not longer then " STR(MQTT_MAX_LWTVALUE_STRLEN) " characters!";
retMsg[F("code")] = WebApiError::MqttLwtOnlineLength; retMsg["code"] = WebApiError::MqttLwtOnlineLength;
retMsg[F("param")][F("max")] = MQTT_MAX_LWTVALUE_STRLEN; retMsg["param"]["max"] = MQTT_MAX_LWTVALUE_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_lwt_offline")].as<String>().length() > MQTT_MAX_LWTVALUE_STRLEN) { if (root["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["message"] = "LWT offline value must not longer then " STR(MQTT_MAX_LWTVALUE_STRLEN) " characters!";
retMsg[F("code")] = WebApiError::MqttLwtOfflineLength; retMsg["code"] = WebApiError::MqttLwtOfflineLength;
retMsg[F("param")][F("max")] = MQTT_MAX_LWTVALUE_STRLEN; retMsg["param"]["max"] = MQTT_MAX_LWTVALUE_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_publish_interval")].as<uint32_t>() < 5 || root[F("mqtt_publish_interval")].as<uint32_t>() > 65535) { if (root["mqtt_publish_interval"].as<uint32_t>() < 5 || root["mqtt_publish_interval"].as<uint32_t>() > 65535) {
retMsg[F("message")] = F("Publish interval must be a number between 5 and 65535!"); retMsg["message"] = "Publish interval must be a number between 5 and 65535!";
retMsg[F("code")] = WebApiError::MqttPublishInterval; retMsg["code"] = WebApiError::MqttPublishInterval;
retMsg[F("param")][F("min")] = 5; retMsg["param"]["min"] = 5;
retMsg[F("param")][F("max")] = 65535; retMsg["param"]["max"] = 65535;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_hass_enabled")].as<bool>()) { if (root["mqtt_hass_enabled"].as<bool>()) {
if (root[F("mqtt_hass_topic")].as<String>().length() > MQTT_MAX_TOPIC_STRLEN) { if (root["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["message"] = "Hass topic must not longer then " STR(MQTT_MAX_TOPIC_STRLEN) " characters!";
retMsg[F("code")] = WebApiError::MqttHassTopicLength; retMsg["code"] = WebApiError::MqttHassTopicLength;
retMsg[F("param")][F("max")] = MQTT_MAX_TOPIC_STRLEN; retMsg["param"]["max"] = MQTT_MAX_TOPIC_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("mqtt_hass_topic")].as<String>().indexOf(' ') != -1) { if (root["mqtt_hass_topic"].as<String>().indexOf(' ') != -1) {
retMsg[F("message")] = F("Hass topic must not contain space characters!"); retMsg["message"] = "Hass topic must not contain space characters!";
retMsg[F("code")] = WebApiError::MqttHassTopicCharacter; retMsg["code"] = WebApiError::MqttHassTopicCharacter;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -290,29 +290,29 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
} }
CONFIG_T& config = Configuration.get(); CONFIG_T& config = Configuration.get();
config.Mqtt_Enabled = root[F("mqtt_enabled")].as<bool>(); config.Mqtt_Enabled = root["mqtt_enabled"].as<bool>();
config.Mqtt_Retain = root[F("mqtt_retain")].as<bool>(); config.Mqtt_Retain = root["mqtt_retain"].as<bool>();
config.Mqtt_Tls = root[F("mqtt_tls")].as<bool>(); config.Mqtt_Tls = root["mqtt_tls"].as<bool>();
strlcpy(config.Mqtt_RootCaCert, root[F("mqtt_root_ca_cert")].as<String>().c_str(), sizeof(config.Mqtt_RootCaCert)); strlcpy(config.Mqtt_RootCaCert, root["mqtt_root_ca_cert"].as<String>().c_str(), sizeof(config.Mqtt_RootCaCert));
config.Mqtt_Port = root[F("mqtt_port")].as<uint>(); config.Mqtt_Port = root["mqtt_port"].as<uint>();
strlcpy(config.Mqtt_Hostname, root[F("mqtt_hostname")].as<String>().c_str(), sizeof(config.Mqtt_Hostname)); strlcpy(config.Mqtt_Hostname, root["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_Username, root["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_Password, root["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_Topic, root["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_LwtTopic, root["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_Online, root["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)); strlcpy(config.Mqtt_LwtValue_Offline, root["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_PublishInterval = root["mqtt_publish_interval"].as<uint32_t>();
config.Mqtt_Hass_Enabled = root[F("mqtt_hass_enabled")].as<bool>(); config.Mqtt_Hass_Enabled = root["mqtt_hass_enabled"].as<bool>();
config.Mqtt_Hass_Expire = root[F("mqtt_hass_expire")].as<bool>(); config.Mqtt_Hass_Expire = root["mqtt_hass_expire"].as<bool>();
config.Mqtt_Hass_Retain = root[F("mqtt_hass_retain")].as<bool>(); config.Mqtt_Hass_Retain = root["mqtt_hass_retain"].as<bool>();
config.Mqtt_Hass_IndividualPanels = root[F("mqtt_hass_individualpanels")].as<bool>(); config.Mqtt_Hass_IndividualPanels = root["mqtt_hass_individualpanels"].as<bool>();
strlcpy(config.Mqtt_Hass_Topic, root[F("mqtt_hass_topic")].as<String>().c_str(), sizeof(config.Mqtt_Hass_Topic)); strlcpy(config.Mqtt_Hass_Topic, root["mqtt_hass_topic"].as<String>().c_str(), sizeof(config.Mqtt_Hass_Topic));
Configuration.write(); Configuration.write();
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Settings saved!"); retMsg["message"] = "Settings saved!";
retMsg[F("code")] = WebApiError::GenericSuccess; retMsg["code"] = WebApiError::GenericSuccess;
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@ -34,22 +34,22 @@ void WebApiNetworkClass::onNetworkStatus(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
root[F("sta_status")] = ((WiFi.getMode() & WIFI_STA) != 0); root["sta_status"] = ((WiFi.getMode() & WIFI_STA) != 0);
root[F("sta_ssid")] = WiFi.SSID(); root["sta_ssid"] = WiFi.SSID();
root[F("sta_rssi")] = WiFi.RSSI(); root["sta_rssi"] = WiFi.RSSI();
root[F("network_hostname")] = NetworkSettings.getHostname(); root["network_hostname"] = NetworkSettings.getHostname();
root[F("network_ip")] = NetworkSettings.localIP().toString(); root["network_ip"] = NetworkSettings.localIP().toString();
root[F("network_netmask")] = NetworkSettings.subnetMask().toString(); root["network_netmask"] = NetworkSettings.subnetMask().toString();
root[F("network_gateway")] = NetworkSettings.gatewayIP().toString(); root["network_gateway"] = NetworkSettings.gatewayIP().toString();
root[F("network_dns1")] = NetworkSettings.dnsIP(0).toString(); root["network_dns1"] = NetworkSettings.dnsIP(0).toString();
root[F("network_dns2")] = NetworkSettings.dnsIP(1).toString(); root["network_dns2"] = NetworkSettings.dnsIP(1).toString();
root[F("network_mac")] = NetworkSettings.macAddress(); root["network_mac"] = NetworkSettings.macAddress();
root[F("network_mode")] = NetworkSettings.NetworkMode() == network_mode::WiFi ? F("Station") : F("Ethernet"); root["network_mode"] = NetworkSettings.NetworkMode() == network_mode::WiFi ? "Station" : "Ethernet";
root[F("ap_status")] = ((WiFi.getMode() & WIFI_AP) != 0); root["ap_status"] = ((WiFi.getMode() & WIFI_AP) != 0);
root[F("ap_ssid")] = NetworkSettings.getApName(); root["ap_ssid"] = NetworkSettings.getApName();
root[F("ap_ip")] = WiFi.softAPIP().toString(); root["ap_ip"] = WiFi.softAPIP().toString();
root[F("ap_mac")] = WiFi.softAPmacAddress(); root["ap_mac"] = WiFi.softAPmacAddress();
root[F("ap_stationnum")] = WiFi.softAPgetStationNum(); root["ap_stationnum"] = WiFi.softAPgetStationNum();
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -65,15 +65,15 @@ void WebApiNetworkClass::onNetworkAdminGet(AsyncWebServerRequest* request)
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
root[F("hostname")] = config.WiFi_Hostname; root["hostname"] = config.WiFi_Hostname;
root[F("dhcp")] = config.WiFi_Dhcp; root["dhcp"] = config.WiFi_Dhcp;
root[F("ipaddress")] = IPAddress(config.WiFi_Ip).toString(); root["ipaddress"] = IPAddress(config.WiFi_Ip).toString();
root[F("netmask")] = IPAddress(config.WiFi_Netmask).toString(); root["netmask"] = IPAddress(config.WiFi_Netmask).toString();
root[F("gateway")] = IPAddress(config.WiFi_Gateway).toString(); root["gateway"] = IPAddress(config.WiFi_Gateway).toString();
root[F("dns1")] = IPAddress(config.WiFi_Dns1).toString(); root["dns1"] = IPAddress(config.WiFi_Dns1).toString();
root[F("dns2")] = IPAddress(config.WiFi_Dns2).toString(); root["dns2"] = IPAddress(config.WiFi_Dns2).toString();
root[F("ssid")] = config.WiFi_Ssid; root["ssid"] = config.WiFi_Ssid;
root[F("password")] = config.WiFi_Password; root["password"] = config.WiFi_Password;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -87,11 +87,11 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -100,8 +100,8 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > 1024) { if (json.length() > 1024) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -111,78 +111,78 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; 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"))) { 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["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
IPAddress ipaddress; IPAddress ipaddress;
if (!ipaddress.fromString(root[F("ipaddress")].as<String>())) { if (!ipaddress.fromString(root["ipaddress"].as<String>())) {
retMsg[F("message")] = F("IP address is invalid!"); retMsg["message"] = "IP address is invalid!";
retMsg[F("code")] = WebApiError::NetworkIpInvalid; retMsg["code"] = WebApiError::NetworkIpInvalid;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
IPAddress netmask; IPAddress netmask;
if (!netmask.fromString(root[F("netmask")].as<String>())) { if (!netmask.fromString(root["netmask"].as<String>())) {
retMsg[F("message")] = F("Netmask is invalid!"); retMsg["message"] = "Netmask is invalid!";
retMsg[F("code")] = WebApiError::NetworkNetmaskInvalid; retMsg["code"] = WebApiError::NetworkNetmaskInvalid;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
IPAddress gateway; IPAddress gateway;
if (!gateway.fromString(root[F("gateway")].as<String>())) { if (!gateway.fromString(root["gateway"].as<String>())) {
retMsg[F("message")] = F("Gateway is invalid!"); retMsg["message"] = "Gateway is invalid!";
retMsg[F("code")] = WebApiError::NetworkGatewayInvalid; retMsg["code"] = WebApiError::NetworkGatewayInvalid;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
IPAddress dns1; IPAddress dns1;
if (!dns1.fromString(root[F("dns1")].as<String>())) { if (!dns1.fromString(root["dns1"].as<String>())) {
retMsg[F("message")] = F("DNS Server IP 1 is invalid!"); retMsg["message"] = "DNS Server IP 1 is invalid!";
retMsg[F("code")] = WebApiError::NetworkDns1Invalid; retMsg["code"] = WebApiError::NetworkDns1Invalid;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
IPAddress dns2; IPAddress dns2;
if (!dns2.fromString(root[F("dns2")].as<String>())) { if (!dns2.fromString(root["dns2"].as<String>())) {
retMsg[F("message")] = F("DNS Server IP 2 is invalid!"); retMsg["message"] = "DNS Server IP 2 is invalid!";
retMsg[F("code")] = WebApiError::NetworkDns2Invalid; retMsg["code"] = WebApiError::NetworkDns2Invalid;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("hostname")].as<String>().length() == 0 || root[F("hostname")].as<String>().length() > WIFI_MAX_HOSTNAME_STRLEN) { if (root["hostname"].as<String>().length() == 0 || root["hostname"].as<String>().length() > WIFI_MAX_HOSTNAME_STRLEN) {
retMsg[F("message")] = F("Hostname must between 1 and " STR(WIFI_MAX_HOSTNAME_STRLEN) " characters long!"); retMsg["message"] = "Hostname must between 1 and " STR(WIFI_MAX_HOSTNAME_STRLEN) " characters long!";
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (NetworkSettings.NetworkMode() == network_mode::WiFi) { if (NetworkSettings.NetworkMode() == network_mode::WiFi) {
if (root[F("ssid")].as<String>().length() == 0 || root[F("ssid")].as<String>().length() > WIFI_MAX_SSID_STRLEN) { if (root["ssid"].as<String>().length() == 0 || root["ssid"].as<String>().length() > WIFI_MAX_SSID_STRLEN) {
retMsg[F("message")] = F("SSID must between 1 and " STR(WIFI_MAX_SSID_STRLEN) " characters long!"); retMsg["message"] = "SSID must between 1 and " STR(WIFI_MAX_SSID_STRLEN) " characters long!";
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
} }
if (root[F("password")].as<String>().length() > WIFI_MAX_PASSWORD_STRLEN - 1) { if (root["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!"); retMsg["message"] = "Password must not be longer than " STR(WIFI_MAX_PASSWORD_STRLEN) " characters long!";
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -209,19 +209,19 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
config.WiFi_Dns2[1] = dns2[1]; config.WiFi_Dns2[1] = dns2[1];
config.WiFi_Dns2[2] = dns2[2]; config.WiFi_Dns2[2] = dns2[2];
config.WiFi_Dns2[3] = dns2[3]; config.WiFi_Dns2[3] = dns2[3];
strlcpy(config.WiFi_Ssid, root[F("ssid")].as<String>().c_str(), sizeof(config.WiFi_Ssid)); strlcpy(config.WiFi_Ssid, root["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_Password, root["password"].as<String>().c_str(), sizeof(config.WiFi_Password));
strlcpy(config.WiFi_Hostname, root[F("hostname")].as<String>().c_str(), sizeof(config.WiFi_Hostname)); strlcpy(config.WiFi_Hostname, root["hostname"].as<String>().c_str(), sizeof(config.WiFi_Hostname));
if (root[F("dhcp")].as<bool>()) { if (root["dhcp"].as<bool>()) {
config.WiFi_Dhcp = true; config.WiFi_Dhcp = true;
} else { } else {
config.WiFi_Dhcp = false; config.WiFi_Dhcp = false;
} }
Configuration.write(); Configuration.write();
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Settings saved!"); retMsg["message"] = "Settings saved!";
retMsg[F("code")] = WebApiError::GenericSuccess; retMsg["code"] = WebApiError::GenericSuccess;
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@ -38,29 +38,29 @@ void WebApiNtpClass::onNtpStatus(AsyncWebServerRequest* request)
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
root[F("ntp_server")] = config.Ntp_Server; root["ntp_server"] = config.Ntp_Server;
root[F("ntp_timezone")] = config.Ntp_Timezone; root["ntp_timezone"] = config.Ntp_Timezone;
root[F("ntp_timezone_descr")] = config.Ntp_TimezoneDescr; root["ntp_timezone_descr"] = config.Ntp_TimezoneDescr;
struct tm timeinfo; struct tm timeinfo;
if (!getLocalTime(&timeinfo, 5)) { if (!getLocalTime(&timeinfo, 5)) {
root[F("ntp_status")] = false; root["ntp_status"] = false;
} else { } else {
root[F("ntp_status")] = true; root["ntp_status"] = true;
} }
char timeStringBuff[50]; char timeStringBuff[50];
strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo); strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo);
root[F("ntp_localtime")] = timeStringBuff; root["ntp_localtime"] = timeStringBuff;
SunPosition.sunriseTime(&timeinfo); SunPosition.sunriseTime(&timeinfo);
strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &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); SunPosition.sunsetTime(&timeinfo);
strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &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(); response->setLength();
request->send(response); request->send(response);
@ -76,11 +76,11 @@ void WebApiNtpClass::onNtpAdminGet(AsyncWebServerRequest* request)
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
root[F("ntp_server")] = config.Ntp_Server; root["ntp_server"] = config.Ntp_Server;
root[F("ntp_timezone")] = config.Ntp_Timezone; root["ntp_timezone"] = config.Ntp_Timezone;
root[F("ntp_timezone_descr")] = config.Ntp_TimezoneDescr; root["ntp_timezone_descr"] = config.Ntp_TimezoneDescr;
root[F("longitude")] = config.Ntp_Longitude; root["longitude"] = config.Ntp_Longitude;
root[F("latitude")] = config.Ntp_Latitude; root["latitude"] = config.Ntp_Latitude;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -94,11 +94,11 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -107,8 +107,8 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > 1024) { if (json.length() > 1024) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -118,59 +118,59 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (!(root.containsKey("ntp_server") && root.containsKey("ntp_timezone") && root.containsKey("longitude") && root.containsKey("latitude"))) { if (!(root.containsKey("ntp_server") && root.containsKey("ntp_timezone") && root.containsKey("longitude") && root.containsKey("latitude"))) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("ntp_server")].as<String>().length() == 0 || root[F("ntp_server")].as<String>().length() > NTP_MAX_SERVER_STRLEN) { if (root["ntp_server"].as<String>().length() == 0 || root["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["message"] = "NTP Server must between 1 and " STR(NTP_MAX_SERVER_STRLEN) " characters long!";
retMsg[F("code")] = WebApiError::NtpServerLength; retMsg["code"] = WebApiError::NtpServerLength;
retMsg[F("param")][F("max")] = NTP_MAX_SERVER_STRLEN; retMsg["param"]["max"] = NTP_MAX_SERVER_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("ntp_timezone")].as<String>().length() == 0 || root[F("ntp_timezone")].as<String>().length() > NTP_MAX_TIMEZONE_STRLEN) { if (root["ntp_timezone"].as<String>().length() == 0 || root["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["message"] = "Timezone must between 1 and " STR(NTP_MAX_TIMEZONE_STRLEN) " characters long!";
retMsg[F("code")] = WebApiError::NtpTimezoneLength; retMsg["code"] = WebApiError::NtpTimezoneLength;
retMsg[F("param")][F("max")] = NTP_MAX_TIMEZONE_STRLEN; retMsg["param"]["max"] = NTP_MAX_TIMEZONE_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("ntp_timezone_descr")].as<String>().length() == 0 || root[F("ntp_timezone_descr")].as<String>().length() > 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[F("message")] = F("Timezone description must between 1 and " STR(NTP_MAX_TIMEZONEDESCR_STRLEN) " characters long!"); retMsg["message"] = "Timezone description must between 1 and " STR(NTP_MAX_TIMEZONEDESCR_STRLEN) " characters long!";
retMsg[F("code")] = WebApiError::NtpTimezoneDescriptionLength; retMsg["code"] = WebApiError::NtpTimezoneDescriptionLength;
retMsg[F("param")][F("max")] = NTP_MAX_TIMEZONEDESCR_STRLEN; retMsg["param"]["max"] = NTP_MAX_TIMEZONEDESCR_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
CONFIG_T& config = Configuration.get(); CONFIG_T& config = Configuration.get();
strlcpy(config.Ntp_Server, root[F("ntp_server")].as<String>().c_str(), sizeof(config.Ntp_Server)); strlcpy(config.Ntp_Server, root["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_Timezone, root["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)); strlcpy(config.Ntp_TimezoneDescr, root["ntp_timezone_descr"].as<String>().c_str(), sizeof(config.Ntp_TimezoneDescr));
config.Ntp_Latitude = root[F("latitude")].as<double>(); config.Ntp_Latitude = root["latitude"].as<double>();
config.Ntp_Longitude = root[F("longitude")].as<double>(); config.Ntp_Longitude = root["longitude"].as<double>();
Configuration.write(); Configuration.write();
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Settings saved!"); retMsg["message"] = "Settings saved!";
retMsg[F("code")] = WebApiError::GenericSuccess; retMsg["code"] = WebApiError::GenericSuccess;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -190,17 +190,17 @@ void WebApiNtpClass::onNtpTimeGet(AsyncWebServerRequest* request)
struct tm timeinfo; struct tm timeinfo;
if (!getLocalTime(&timeinfo, 5)) { if (!getLocalTime(&timeinfo, 5)) {
root[F("ntp_status")] = false; root["ntp_status"] = false;
} else { } else {
root[F("ntp_status")] = true; root["ntp_status"] = true;
} }
root[F("year")] = timeinfo.tm_year + 1900; root["year"] = timeinfo.tm_year + 1900;
root[F("month")] = timeinfo.tm_mon + 1; root["month"] = timeinfo.tm_mon + 1;
root[F("day")] = timeinfo.tm_mday; root["day"] = timeinfo.tm_mday;
root[F("hour")] = timeinfo.tm_hour; root["hour"] = timeinfo.tm_hour;
root[F("minute")] = timeinfo.tm_min; root["minute"] = timeinfo.tm_min;
root[F("second")] = timeinfo.tm_sec; root["second"] = timeinfo.tm_sec;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -214,11 +214,11 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -227,8 +227,8 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > 1024) { if (json.length() > 1024) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -238,8 +238,8 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -251,89 +251,89 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request)
&& root.containsKey("hour") && root.containsKey("hour")
&& root.containsKey("minute") && root.containsKey("minute")
&& root.containsKey("second"))) { && root.containsKey("second"))) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("year")].as<uint>() < 2022 || root[F("year")].as<uint>() > 2100) { if (root["year"].as<uint>() < 2022 || root["year"].as<uint>() > 2100) {
retMsg[F("message")] = F("Year must be a number between 2022 and 2100!"); retMsg["message"] = "Year must be a number between 2022 and 2100!";
retMsg[F("code")] = WebApiError::NtpYearInvalid; retMsg["code"] = WebApiError::NtpYearInvalid;
retMsg[F("param")][F("min")] = 2022; retMsg["param"]["min"] = 2022;
retMsg[F("param")][F("max")] = 2100; retMsg["param"]["max"] = 2100;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("month")].as<uint>() < 1 || root[F("month")].as<uint>() > 12) { if (root["month"].as<uint>() < 1 || root["month"].as<uint>() > 12) {
retMsg[F("message")] = F("Month must be a number between 1 and 12!"); retMsg["message"] = "Month must be a number between 1 and 12!";
retMsg[F("code")] = WebApiError::NtpMonthInvalid; retMsg["code"] = WebApiError::NtpMonthInvalid;
retMsg[F("param")][F("min")] = 1; retMsg["param"]["min"] = 1;
retMsg[F("param")][F("max")] = 12; retMsg["param"]["max"] = 12;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("day")].as<uint>() < 1 || root[F("day")].as<uint>() > 31) { if (root["day"].as<uint>() < 1 || root["day"].as<uint>() > 31) {
retMsg[F("message")] = F("Day must be a number between 1 and 31!"); retMsg["message"] = "Day must be a number between 1 and 31!";
retMsg[F("code")] = WebApiError::NtpDayInvalid; retMsg["code"] = WebApiError::NtpDayInvalid;
retMsg[F("param")][F("min")] = 1; retMsg["param"]["min"] = 1;
retMsg[F("param")][F("max")] = 31; retMsg["param"]["max"] = 31;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("hour")].as<uint>() > 23) { if (root["hour"].as<uint>() > 23) {
retMsg[F("message")] = F("Hour must be a number between 0 and 23!"); retMsg["message"] = "Hour must be a number between 0 and 23!";
retMsg[F("code")] = WebApiError::NtpHourInvalid; retMsg["code"] = WebApiError::NtpHourInvalid;
retMsg[F("param")][F("min")] = 0; retMsg["param"]["min"] = 0;
retMsg[F("param")][F("max")] = 23; retMsg["param"]["max"] = 23;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("minute")].as<uint>() > 59) { if (root["minute"].as<uint>() > 59) {
retMsg[F("message")] = F("Minute must be a number between 0 and 59!"); retMsg["message"] = "Minute must be a number between 0 and 59!";
retMsg[F("code")] = WebApiError::NtpMinuteInvalid; retMsg["code"] = WebApiError::NtpMinuteInvalid;
retMsg[F("param")][F("min")] = 0; retMsg["param"]["min"] = 0;
retMsg[F("param")][F("max")] = 59; retMsg["param"]["max"] = 59;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("second")].as<uint>() > 59) { if (root["second"].as<uint>() > 59) {
retMsg[F("message")] = F("Second must be a number between 0 and 59!"); retMsg["message"] = "Second must be a number between 0 and 59!";
retMsg[F("code")] = WebApiError::NtpSecondInvalid; retMsg["code"] = WebApiError::NtpSecondInvalid;
retMsg[F("param")][F("min")] = 0; retMsg["param"]["min"] = 0;
retMsg[F("param")][F("max")] = 59; retMsg["param"]["max"] = 59;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
tm local; tm local;
local.tm_sec = root[F("second")].as<uint>(); // seconds after the minute - [ 0 to 59 ] local.tm_sec = root["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_min = root["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_hour = root["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_mday = root["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_mon = root["month"].as<uint>() - 1; // months since January - [ 0 to 11 ]
local.tm_year = root[F("year")].as<uint>() - 1900; // years since 1900 local.tm_year = root["year"].as<uint>() - 1900; // years since 1900
local.tm_isdst = -1; local.tm_isdst = -1;
time_t t = mktime(&local); time_t t = mktime(&local);
struct timeval now = { .tv_sec = t, .tv_usec = 0 }; struct timeval now = { .tv_sec = t, .tv_usec = 0 };
settimeofday(&now, NULL); settimeofday(&now, NULL);
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Time updated!"); retMsg["message"] = "Time updated!";
retMsg[F("code")] = WebApiError::NtpTimeUpdated; retMsg["code"] = WebApiError::NtpTimeUpdated;
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@ -58,11 +58,11 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -71,8 +71,8 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > 1024) { if (json.length() > 1024) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -82,8 +82,8 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -91,43 +91,43 @@ void WebApiPowerClass::onPowerPost(AsyncWebServerRequest* request)
if (!(root.containsKey("serial") if (!(root.containsKey("serial")
&& (root.containsKey("power") || root.containsKey("restart")))) { && (root.containsKey("power") || root.containsKey("restart")))) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("serial")].as<uint64_t>() == 0) { if (root["serial"].as<uint64_t>() == 0) {
retMsg[F("message")] = F("Serial must be a number > 0!"); retMsg["message"] = "Serial must be a number > 0!";
retMsg[F("code")] = WebApiError::PowerSerialZero; retMsg["code"] = WebApiError::PowerSerialZero;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; 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); auto inv = Hoymiles.getInverterBySerial(serial);
if (inv == nullptr) { if (inv == nullptr) {
retMsg[F("message")] = F("Invalid inverter specified!"); retMsg["message"] = "Invalid inverter specified!";
retMsg[F("code")] = WebApiError::PowerInvalidInverter; retMsg["code"] = WebApiError::PowerInvalidInverter;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root.containsKey("power")) { if (root.containsKey("power")) {
uint16_t power = root[F("power")].as<bool>(); uint16_t power = root["power"].as<bool>();
inv->sendPowerControlRequest(Hoymiles.getRadio(), power); inv->sendPowerControlRequest(Hoymiles.getRadio(), power);
} else { } else {
if (root[F("restart")].as<bool>()) { if (root["restart"].as<bool>()) {
inv->sendRestartControlRequest(Hoymiles.getRadio()); inv->sendRestartControlRequest(Hoymiles.getRadio());
} }
} }
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Settings saved!"); retMsg["message"] = "Settings saved!";
retMsg[F("code")] = WebApiError::GenericSuccess; retMsg["code"] = WebApiError::GenericSuccess;
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@ -29,29 +29,29 @@ void WebApiPrometheusClass::onPrometheusMetricsGet(AsyncWebServerRequest* reques
try { try {
auto stream = request->beginResponseStream("text/plain; charset=utf-8", 40960); auto stream = request->beginResponseStream("text/plain; charset=utf-8", 40960);
stream->print(F("# HELP opendtu_build Build info\n")); stream->print("# HELP opendtu_build Build info\n");
stream->print(F("# TYPE opendtu_build gauge\n")); stream->print("# TYPE opendtu_build gauge\n");
stream->printf("opendtu_build{name=\"%s\",id=\"%s\",version=\"%d.%d.%d\"} 1\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); 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("# HELP opendtu_platform Platform info\n");
stream->print(F("# TYPE opendtu_platform gauge\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->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("# HELP opendtu_uptime Uptime in seconds\n");
stream->print(F("# TYPE opendtu_uptime counter\n")); stream->print("# TYPE opendtu_uptime counter\n");
stream->printf("opendtu_uptime %lld\n", esp_timer_get_time() / 1000000); stream->printf("opendtu_uptime %lld\n", esp_timer_get_time() / 1000000);
stream->print(F("# HELP opendtu_heap_size System memory size\n")); stream->print("# HELP opendtu_heap_size System memory size\n");
stream->print(F("# TYPE opendtu_heap_size gauge\n")); stream->print("# TYPE opendtu_heap_size gauge\n");
stream->printf("opendtu_heap_size %zu\n", ESP.getHeapSize()); stream->printf("opendtu_heap_size %zu\n", ESP.getHeapSize());
stream->print(F("# HELP opendtu_free_heap_size System free memory\n")); stream->print("# HELP opendtu_free_heap_size System free memory\n");
stream->print(F("# TYPE opendtu_free_heap_size gauge\n")); stream->print("# TYPE opendtu_free_heap_size gauge\n");
stream->printf("opendtu_free_heap_size %zu\n", ESP.getFreeHeap()); stream->printf("opendtu_free_heap_size %zu\n", ESP.getFreeHeap());
stream->print(F("# HELP wifi_rssi WiFi RSSI\n")); stream->print("# HELP wifi_rssi WiFi RSSI\n");
stream->print(F("# TYPE wifi_rssi gauge\n")); stream->print("# TYPE wifi_rssi gauge\n");
stream->printf("wifi_rssi %d\n", WiFi.RSSI()); stream->printf("wifi_rssi %d\n", WiFi.RSSI());
for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) { for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) {
@ -60,8 +60,8 @@ void WebApiPrometheusClass::onPrometheusMetricsGet(AsyncWebServerRequest* reques
String serial = inv->serialString(); String serial = inv->serialString();
const char* name = inv->name(); const char* name = inv->name();
if (i == 0) { if (i == 0) {
stream->print(F("# HELP opendtu_last_update last update from inverter in s\n")); stream->print("# HELP opendtu_last_update last update from inverter in s\n");
stream->print(F("# TYPE opendtu_last_update gauge\n")); stream->print("# TYPE opendtu_last_update gauge\n");
} }
stream->printf("opendtu_last_update{serial=\"%s\",unit=\"%d\",name=\"%s\"} %d\n", stream->printf("opendtu_last_update{serial=\"%s\",unit=\"%d\",name=\"%s\"} %d\n",
serial.c_str(), i, name, inv->Statistics()->getLastUpdate() / 1000); serial.c_str(), i, name, inv->Statistics()->getLastUpdate() / 1000);
@ -93,7 +93,7 @@ void WebApiPrometheusClass::onPrometheusMetricsGet(AsyncWebServerRequest* reques
} }
} }
} }
stream->addHeader(F("Cache-Control"), F("no-cache")); stream->addHeader("Cache-Control", "no-cache");
request->send(stream); request->send(stream);
} catch (std::bad_alloc& bad_alloc) { } catch (std::bad_alloc& bad_alloc) {
@ -132,8 +132,8 @@ void WebApiPrometheusClass::addPanelInfo(AsyncResponseStream* stream, String& se
const bool printHelp = (idx == 0 && channel == 0); const bool printHelp = (idx == 0 && channel == 0);
if (printHelp) { if (printHelp) {
stream->print(F("# HELP opendtu_PanelInfo panel information\n")); stream->print("# HELP opendtu_PanelInfo panel information\n");
stream->print(F("# TYPE opendtu_PanelInfo gauge\n")); stream->print("# TYPE opendtu_PanelInfo gauge\n");
} }
stream->printf("opendtu_PanelInfo{serial=\"%s\",unit=\"%d\",name=\"%s\",channel=\"%d\",panelname=\"%s\"} 1\n", stream->printf("opendtu_PanelInfo{serial=\"%s\",unit=\"%d\",name=\"%s\",channel=\"%d\",panelname=\"%s\"} 1\n",
serial.c_str(), serial.c_str(),
@ -144,8 +144,8 @@ void WebApiPrometheusClass::addPanelInfo(AsyncResponseStream* stream, String& se
); );
if (printHelp) { if (printHelp) {
stream->print(F("# HELP opendtu_MaxPower panel maximum output power\n")); stream->print("# HELP opendtu_MaxPower panel maximum output power\n");
stream->print(F("# TYPE opendtu_MaxPower gauge\n")); stream->print("# TYPE opendtu_MaxPower gauge\n");
} }
stream->printf("opendtu_MaxPower{serial=\"%s\",unit=\"%d\",name=\"%s\",channel=\"%d\"} %d\n", stream->printf("opendtu_MaxPower{serial=\"%s\",unit=\"%d\",name=\"%s\",channel=\"%d\"} %d\n",
serial.c_str(), serial.c_str(),
@ -156,8 +156,8 @@ void WebApiPrometheusClass::addPanelInfo(AsyncResponseStream* stream, String& se
); );
if (printHelp) { if (printHelp) {
stream->print(F("# HELP opendtu_YieldTotalOffset panel yield offset (for used inverters)\n")); stream->print("# HELP opendtu_YieldTotalOffset panel yield offset (for used inverters)\n");
stream->print(F("# TYPE opendtu_YieldTotalOffset gauge\n")); stream->print("# TYPE opendtu_YieldTotalOffset gauge\n");
} }
stream->printf("opendtu_YieldTotalOffset{serial=\"%s\",unit=\"%d\",name=\"%s\",channel=\"%d\"} %f\n", stream->printf("opendtu_YieldTotalOffset{serial=\"%s\",unit=\"%d\",name=\"%s\",channel=\"%d\"} %f\n",
serial.c_str(), serial.c_str(),

View File

@ -34,8 +34,8 @@ void WebApiSecurityClass::onSecurityGet(AsyncWebServerRequest* request)
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
const CONFIG_T& config = Configuration.get(); const CONFIG_T& config = Configuration.get();
root[F("password")] = config.Security_Password; root["password"] = config.Security_Password;
root[F("allow_readonly")] = config.Security_AllowReadonly; root["allow_readonly"] = config.Security_AllowReadonly;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -49,11 +49,11 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("warning"); retMsg["type"] = "warning";
if (!request->hasParam("data", true)) { if (!request->hasParam("data", true)) {
retMsg[F("message")] = F("No values found!"); retMsg["message"] = "No values found!";
retMsg[F("code")] = WebApiError::GenericNoValueFound; retMsg["code"] = WebApiError::GenericNoValueFound;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -62,8 +62,8 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
String json = request->getParam("data", true)->value(); String json = request->getParam("data", true)->value();
if (json.length() > 1024) { if (json.length() > 1024) {
retMsg[F("message")] = F("Data too large!"); retMsg["message"] = "Data too large!";
retMsg[F("code")] = WebApiError::GenericDataTooLarge; retMsg["code"] = WebApiError::GenericDataTooLarge;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -73,8 +73,8 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
DeserializationError error = deserializeJson(root, json); DeserializationError error = deserializeJson(root, json);
if (error) { if (error) {
retMsg[F("message")] = F("Failed to parse data!"); retMsg["message"] = "Failed to parse data!";
retMsg[F("code")] = WebApiError::GenericParseError; retMsg["code"] = WebApiError::GenericParseError;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
@ -82,30 +82,30 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
if (!root.containsKey("password") if (!root.containsKey("password")
&& root.containsKey("allow_readonly")) { && root.containsKey("allow_readonly")) {
retMsg[F("message")] = F("Values are missing!"); retMsg["message"] = "Values are missing!";
retMsg[F("code")] = WebApiError::GenericValueMissing; retMsg["code"] = WebApiError::GenericValueMissing;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
if (root[F("password")].as<String>().length() < 8 || root[F("password")].as<String>().length() > WIFI_MAX_PASSWORD_STRLEN) { if (root["password"].as<String>().length() < 8 || root["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["message"] = "Password must between 8 and " STR(WIFI_MAX_PASSWORD_STRLEN) " characters long!";
retMsg[F("code")] = WebApiError::SecurityPasswordLength; retMsg["code"] = WebApiError::SecurityPasswordLength;
retMsg[F("param")][F("max")] = WIFI_MAX_PASSWORD_STRLEN; retMsg["param"]["max"] = WIFI_MAX_PASSWORD_STRLEN;
response->setLength(); response->setLength();
request->send(response); request->send(response);
return; return;
} }
CONFIG_T& config = Configuration.get(); CONFIG_T& config = Configuration.get();
strlcpy(config.Security_Password, root[F("password")].as<String>().c_str(), sizeof(config.Security_Password)); strlcpy(config.Security_Password, root["password"].as<String>().c_str(), sizeof(config.Security_Password));
config.Security_AllowReadonly = root[F("allow_readonly")].as<bool>(); config.Security_AllowReadonly = root["allow_readonly"].as<bool>();
Configuration.write(); Configuration.write();
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Settings saved!"); retMsg["message"] = "Settings saved!";
retMsg[F("code")] = WebApiError::GenericSuccess; retMsg["code"] = WebApiError::GenericSuccess;
response->setLength(); response->setLength();
request->send(response); request->send(response);
@ -119,9 +119,9 @@ void WebApiSecurityClass::onAuthenticateGet(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject retMsg = response->getRoot(); JsonObject retMsg = response->getRoot();
retMsg[F("type")] = F("success"); retMsg["type"] = "success";
retMsg[F("message")] = F("Authentication successful!"); retMsg["message"] = "Authentication successful!";
retMsg[F("code")] = WebApiError::SecurityAuthSuccess; retMsg["code"] = WebApiError::SecurityAuthSuccess;
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@ -37,40 +37,40 @@ void WebApiSysstatusClass::onSystemStatus(AsyncWebServerRequest* request)
AsyncJsonResponse* response = new AsyncJsonResponse(); AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
root[F("hostname")] = NetworkSettings.getHostname(); root["hostname"] = NetworkSettings.getHostname();
root[F("sdkversion")] = ESP.getSdkVersion(); root["sdkversion"] = ESP.getSdkVersion();
root[F("cpufreq")] = ESP.getCpuFreqMHz(); root["cpufreq"] = ESP.getCpuFreqMHz();
root[F("heap_total")] = ESP.getHeapSize(); root["heap_total"] = ESP.getHeapSize();
root[F("heap_used")] = ESP.getHeapSize() - ESP.getFreeHeap(); root["heap_used"] = ESP.getHeapSize() - ESP.getFreeHeap();
root[F("sketch_total")] = ESP.getFreeSketchSpace(); root["sketch_total"] = ESP.getFreeSketchSpace();
root[F("sketch_used")] = ESP.getSketchSize(); root["sketch_used"] = ESP.getSketchSize();
root[F("littlefs_total")] = LittleFS.totalBytes(); root["littlefs_total"] = LittleFS.totalBytes();
root[F("littlefs_used")] = LittleFS.usedBytes(); root["littlefs_used"] = LittleFS.usedBytes();
root[F("chiprevision")] = ESP.getChipRevision(); root["chiprevision"] = ESP.getChipRevision();
root[F("chipmodel")] = ESP.getChipModel(); root["chipmodel"] = ESP.getChipModel();
root[F("chipcores")] = ESP.getChipCores(); root["chipcores"] = ESP.getChipCores();
String reason; String reason;
reason = ResetReason.get_reset_reason_verbose(0); reason = ResetReason.get_reset_reason_verbose(0);
root[F("resetreason_0")] = reason; root["resetreason_0"] = reason;
reason = ResetReason.get_reset_reason_verbose(1); 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]; char version[16];
snprintf(version, sizeof(version), "%d.%d.%d", CONFIG_VERSION >> 24 & 0xff, CONFIG_VERSION >> 16 & 0xff, CONFIG_VERSION >> 8 & 0xff); 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["config_version"] = version;
root[F("git_hash")] = AUTO_GIT_HASH; 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["radio_connected"] = Hoymiles.getRadio()->isConnected();
root[F("radio_pvariant")] = Hoymiles.getRadio()->isPVariant(); root["radio_pvariant"] = Hoymiles.getRadio()->isPVariant();
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@ -105,17 +105,17 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
JsonObject invObject = invArray.createNestedObject(); JsonObject invObject = invArray.createNestedObject();
invObject[F("serial")] = inv->serialString(); invObject["serial"] = inv->serialString();
invObject[F("name")] = inv->name(); invObject["name"] = inv->name();
invObject[F("data_age")] = (millis() - inv->Statistics()->getLastUpdate()) / 1000; invObject["data_age"] = (millis() - inv->Statistics()->getLastUpdate()) / 1000;
invObject[F("poll_enabled")] = inv->getEnablePolling(); invObject["poll_enabled"] = inv->getEnablePolling();
invObject[F("reachable")] = inv->isReachable(); invObject["reachable"] = inv->isReachable();
invObject[F("producing")] = inv->isProducing(); invObject["producing"] = inv->isProducing();
invObject[F("limit_relative")] = inv->SystemConfigPara()->getLimitPercent(); invObject["limit_relative"] = inv->SystemConfigPara()->getLimitPercent();
if (inv->DevInfo()->getMaxPower() > 0) { 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 { } else {
invObject[F("limit_absolute")] = -1; invObject["limit_absolute"] = -1;
} }
// Loop all channels // Loop all channels
@ -125,14 +125,14 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
if (t == TYPE_DC) { if (t == TYPE_DC) {
INVERTER_CONFIG_T* inv_cfg = Configuration.getInverterConfig(inv->serial()); INVERTER_CONFIG_T* inv_cfg = Configuration.getInverterConfig(inv->serial());
if (inv_cfg != nullptr) { 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_PAC);
addField(chanTypeObj, i, inv, t, c, FLD_UAC); addField(chanTypeObj, i, inv, t, c, FLD_UAC);
addField(chanTypeObj, i, inv, t, c, FLD_IAC); addField(chanTypeObj, i, inv, t, c, FLD_IAC);
if (t == TYPE_AC) { 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 { } else {
addField(chanTypeObj, i, inv, t, c, FLD_PDC); addField(chanTypeObj, i, inv, t, c, FLD_PDC);
} }
@ -152,9 +152,9 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
} }
if (inv->Statistics()->hasChannelFieldValue(TYPE_INV, CH0, FLD_EVT_LOG)) { if (inv->Statistics()->hasChannelFieldValue(TYPE_INV, CH0, FLD_EVT_LOG)) {
invObject[F("events")] = inv->EventLog()->getEntryCount(); invObject["events"] = inv->EventLog()->getEntryCount();
} else { } else {
invObject[F("events")] = -1; invObject["events"] = -1;
} }
if (inv->Statistics()->getLastUpdate() > _newestInverterTimestamp) { if (inv->Statistics()->getLastUpdate() > _newestInverterTimestamp) {
@ -176,12 +176,12 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
JsonObject hintObj = root.createNestedObject("hints"); JsonObject hintObj = root.createNestedObject("hints");
struct tm timeinfo; struct tm timeinfo;
hintObj[F("time_sync")] = !getLocalTime(&timeinfo, 5); hintObj["time_sync"] = !getLocalTime(&timeinfo, 5);
hintObj[F("radio_problem")] = (!Hoymiles.getRadio()->isConnected() || !Hoymiles.getRadio()->isPVariant()); hintObj["radio_problem"] = (!Hoymiles.getRadio()->isConnected() || !Hoymiles.getRadio()->isPVariant());
if (!strcmp(Configuration.get().Security_Password, ACCESS_POINT_PASSWORD)) { if (!strcmp(Configuration.get().Security_Password, ACCESS_POINT_PASSWORD)) {
hintObj[F("default_password")] = true; hintObj["default_password"] = true;
} else { } else {
hintObj[F("default_password")] = false; hintObj["default_password"] = false;
} }
JsonObject vedirectObj = root.createNestedObject("vedirect"); JsonObject vedirectObj = root.createNestedObject("vedirect");

View File

@ -35,67 +35,67 @@ void setup()
while (!Serial) while (!Serial)
yield(); yield();
MessageOutput.println(); MessageOutput.println();
MessageOutput.println(F("Starting OpenDTU")); MessageOutput.println("Starting OpenDTU");
// Initialize file system // Initialize file system
MessageOutput.print(F("Initialize FS... ")); MessageOutput.print("Initialize FS... ");
if (!LittleFS.begin(false)) { // Do not format if mount failed 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)) { if (!LittleFS.begin(true)) {
MessageOutput.print("success"); MessageOutput.print("success");
} else { } else {
MessageOutput.print("failed"); MessageOutput.print("failed");
} }
} else { } else {
MessageOutput.println(F("done")); MessageOutput.println("done");
} }
// Read configuration values // Read configuration values
MessageOutput.print(F("Reading configuration... ")); MessageOutput.print("Reading configuration... ");
if (!Configuration.read()) { if (!Configuration.read()) {
MessageOutput.print(F("initializing... ")); MessageOutput.print("initializing... ");
Configuration.init(); Configuration.init();
if (Configuration.write()) { if (Configuration.write()) {
MessageOutput.print(F("written... ")); MessageOutput.print("written... ");
} else { } else {
MessageOutput.print(F("failed... ")); MessageOutput.print("failed... ");
} }
} }
if (Configuration.get().Cfg_Version != CONFIG_VERSION) { if (Configuration.get().Cfg_Version != CONFIG_VERSION) {
MessageOutput.print(F("migrated... ")); MessageOutput.print("migrated... ");
Configuration.migrate(); Configuration.migrate();
} }
CONFIG_T& config = Configuration.get(); CONFIG_T& config = Configuration.get();
MessageOutput.println(F("done")); MessageOutput.println("done");
// Load PinMapping // Load PinMapping
MessageOutput.print(F("Reading PinMapping... ")); MessageOutput.print("Reading PinMapping... ");
if (PinMapping.init(String(Configuration.get().Dev_PinMapping))) { if (PinMapping.init(String(Configuration.get().Dev_PinMapping))) {
MessageOutput.print(F("found valid mapping ")); MessageOutput.print("found valid mapping ");
} else { } else {
MessageOutput.print(F("using default config ")); MessageOutput.print("using default config ");
} }
const PinMapping_t& pin = PinMapping.get(); const PinMapping_t& pin = PinMapping.get();
MessageOutput.println(F("done")); MessageOutput.println("done");
// Initialize WiFi // Initialize WiFi
MessageOutput.print(F("Initialize Network... ")); MessageOutput.print("Initialize Network... ");
NetworkSettings.init(); NetworkSettings.init();
MessageOutput.println(F("done")); MessageOutput.println("done");
NetworkSettings.applyConfig(); NetworkSettings.applyConfig();
// Initialize NTP // Initialize NTP
MessageOutput.print(F("Initialize NTP... ")); MessageOutput.print("Initialize NTP... ");
NtpSettings.init(); NtpSettings.init();
MessageOutput.println(F("done")); MessageOutput.println("done");
// Initialize SunPosition // Initialize SunPosition
MessageOutput.print(F("Initialize SunPosition... ")); MessageOutput.print("Initialize SunPosition... ");
SunPosition.init(); SunPosition.init();
MessageOutput.println(F("done")); MessageOutput.println("done");
// Initialize MqTT // Initialize MqTT
MessageOutput.print(F("Initialize MqTT... ")); MessageOutput.print("Initialize MqTT... ");
MqttSettings.init(); MqttSettings.init();
MqttHandleDtu.init(); MqttHandleDtu.init();
MqttHandleInverter.init(); MqttHandleInverter.init();
@ -103,15 +103,15 @@ void setup()
MqttHandleHass.init(); MqttHandleHass.init();
MqttHandleVedirectHass.init(); MqttHandleVedirectHass.init();
MqttHandleHuawei.init(); MqttHandleHuawei.init();
MessageOutput.println(F("done")); MessageOutput.println("done");
// Initialize WebApi // Initialize WebApi
MessageOutput.print(F("Initialize WebApi... ")); MessageOutput.print("Initialize WebApi... ");
WebApi.init(); WebApi.init();
MessageOutput.println(F("done")); MessageOutput.println("done");
// Initialize Display // Initialize Display
MessageOutput.print(F("Initialize Display... ")); MessageOutput.print("Initialize Display... ");
Display.init( Display.init(
static_cast<DisplayType_t>(pin.display_type), static_cast<DisplayType_t>(pin.display_type),
pin.display_data, pin.display_data,
@ -123,12 +123,12 @@ void setup()
Display.enableScreensaver = config.Display_ScreenSaver; Display.enableScreensaver = config.Display_ScreenSaver;
Display.setContrast(config.Display_Contrast); Display.setContrast(config.Display_Contrast);
Display.setStartupDisplay(); Display.setStartupDisplay();
MessageOutput.println(F("done")); MessageOutput.println("done");
// Check for default DTU serial // 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) { 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(); uint64_t dtuId = Utils::generateDtuSerial();
MessageOutput.printf("%0x%08x... ", MessageOutput.printf("%0x%08x... ",
((uint32_t)((dtuId >> 32) & 0xFFFFFFFF)), ((uint32_t)((dtuId >> 32) & 0xFFFFFFFF)),
@ -136,7 +136,7 @@ void setup()
config.Dtu_Serial = dtuId; config.Dtu_Serial = dtuId;
Configuration.write(); Configuration.write();
} }
MessageOutput.println(F("done")); MessageOutput.println("done");
InverterSettings.init(); InverterSettings.init();