diff --git a/inc/hoymiles/dtu.h b/inc/hoymiles/dtu.h index 135e4a4..b5f98bc 100644 --- a/inc/hoymiles/dtu.h +++ b/inc/hoymiles/dtu.h @@ -31,6 +31,8 @@ class Dtu { void printMicroinverters(std::vector ¶metersToGet, bool allParameters, std::vector µinvertersToGet, bool shortNames, bool printTodayProduction, bool printTotalProduction); + void setStatusMicroinverters(uint16_t value, std::string statusName, std::vector& microinvertersToSet); + ~Dtu(); }; diff --git a/inc/hoymiles/microinverter.h b/inc/hoymiles/microinverter.h index 1172db8..26623aa 100644 --- a/inc/hoymiles/microinverter.h +++ b/inc/hoymiles/microinverter.h @@ -41,6 +41,8 @@ class Microinverter { long long getTotalProduction(); void setStatus(std::vector> portsToSet, std::string statusName); + + void setStatusWholeMicroinverter(uint16_t value, std::string statusName); }; #endif \ No newline at end of file diff --git a/src/hoymiles/dtu.cpp b/src/hoymiles/dtu.cpp index ec51a3c..0f7ce54 100644 --- a/src/hoymiles/dtu.cpp +++ b/src/hoymiles/dtu.cpp @@ -122,4 +122,23 @@ void Dtu::printMicroinverters(std::vector ¶metersToGet, bool al } microinvertersToGetIterator++; } +} + +void Dtu::setStatusMicroinverters(uint16_t value, std::string statusName, std::vector& microinvertersToSet) { + if (microinvertersToSet.empty()) { + std::vector::iterator microinvertersIterator = this->microinverters.begin(); + while (microinvertersIterator != this->microinverters.end()) { + microinvertersToSet.push_back(microinvertersIterator->serialNumber); + microinvertersIterator++; + } + } + + std::vector::iterator microinvertersToSetIterator = microinvertersToSet.begin(); + while(microinvertersToSetIterator != microinvertersToSet.end()) { + std::pair microinverterPair = this->getMicroinverterBySerialNumber(*microinvertersToSetIterator); + if(microinverterPair.second) { + microinverterPair.first->setStatusWholeMicroinverter(value, statusName); + } + microinvertersToSetIterator++; + } } \ No newline at end of file diff --git a/src/hoymiles/microinverter.cpp b/src/hoymiles/microinverter.cpp index 858b11a..31e2044 100644 --- a/src/hoymiles/microinverter.cpp +++ b/src/hoymiles/microinverter.cpp @@ -56,7 +56,7 @@ void Microinverter::updateStatusParameters() { int portsRead = 0; while (portsRead < this->ports.size()) { int portsToRead = 0; - while (portsToRead * 6 < (10 - 6) && (portsToRead + portsRead) < this->ports.size()) { + while (portsToRead * 6 < (128 - 6) && (portsToRead + portsRead) < this->ports.size()) { portsToRead++; } @@ -70,6 +70,9 @@ void Microinverter::updateStatusParameters() { this->age++; return; } + else { + this->age = 0; + } for (int i{0}; i < portsToRead; i++) { this->ports.at(i + portsRead).setStatusesFromMicroinverterArray(registers, i * 6); @@ -115,7 +118,22 @@ long long Microinverter::getTotalProduction() { void Microinverter::setStatus(std::vector> portsToSet, std::string statusName) { std::vector>::iterator portsToSetIterator = portsToSet.begin(); while(portsToSetIterator != portsToSet.end()) { - this->ports.at(portsToSetIterator->first).getStatusByName(statusName).first.get()->writeValue(portsToSetIterator->second, *this->modbus, this->ports.at(portsToSetIterator->first).statusPortStartAddress); + try { + if(this->ports.at(portsToSetIterator->first).getStatusByName(statusName).second) { + this->ports.at(portsToSetIterator->first).getStatusByName(statusName).first->writeValue(portsToSetIterator->second, *this->modbus, this->statusStartAddress); + } + } + catch(const std::out_of_range& outOfRange) { + std::cerr << outOfRange.what() << std::endl; + } portsToSetIterator++; } +} + +void Microinverter::setStatusWholeMicroinverter(uint16_t value, std::string statusName) { + if(this->ports.begin() != this->ports.end()) { + if(this->ports.begin()->getStatusByName(statusName).second) { + this->ports.begin()->getStatusByName(statusName).first.get()->writeValue(value, *this->modbus, this->ports.begin()->statusPortStartAddress); + } + } } \ No newline at end of file diff --git a/src/hoymiles/port.cpp b/src/hoymiles/port.cpp index 6a9c7d0..72f839c 100644 --- a/src/hoymiles/port.cpp +++ b/src/hoymiles/port.cpp @@ -50,7 +50,6 @@ void Port::populateParameters() { this->parameters.push_back(std::make_shared()); - this->statusParameters.push_back(std::make_shared()); this->statusParameters.push_back(std::make_shared()); @@ -199,15 +198,26 @@ void Port::printParameters(std::vector ¶metersToGet, bool allPa } parametersToGetIterator++; } + + std::vector>::iterator statusesToGetIterator = this->statusParameters.begin(); + while (statusesToGetIterator != this->statusParameters.end()) { + std::cout << " "; + if (shortNames) { + std::cout << statusesToGetIterator->get()->shortName; + } else { + std::cout << statusesToGetIterator->get()->name; + } + std::cout << ": " << statusesToGetIterator->get()->getOutputValue() << " |"; + statusesToGetIterator++; + } } void Port::turnOff(class modbus &modbus) { this->getStatusByName("onOff").first.get()->writeValue(0, modbus, this->statusPortStartAddress); } bool Port::isOff(class modbus &modbus) { - if(this->getStatusByName("onOff").first.get()->getValue().first.i == 1) { + if (this->getStatusByName("onOff").first.get()->getValue().first.i == 1) { return true; - } - else { + } else { return false; } } \ No newline at end of file diff --git a/src/hoymiles/portParameters/portParameters.cpp b/src/hoymiles/portParameters/portParameters.cpp index 1b404ec..d7bbb43 100644 --- a/src/hoymiles/portParameters/portParameters.cpp +++ b/src/hoymiles/portParameters/portParameters.cpp @@ -48,4 +48,4 @@ PortParameterLinkStatus::PortParameterLinkStatus() : PortParameterInt("linkStatu PortParameterOnOff::PortParameterOnOff() : PortParameterInt("onOff", "of", "", true, true, 0x0000, 1) {} -PortParameterLimitActivePower::PortParameterLimitActivePower() : PortParameterInt("limitActivePower", "lAP", "", true, true, 0x0001, 1) {} \ No newline at end of file +PortParameterLimitActivePower::PortParameterLimitActivePower() : PortParameterInt("limitActivePower", "lAP", "%", true, true, 0x0001, 1) {} \ No newline at end of file diff --git a/src/hoymiles/portParameters/portParametersGeneric.cpp b/src/hoymiles/portParameters/portParametersGeneric.cpp index 502d148..eb34b9d 100644 --- a/src/hoymiles/portParameters/portParametersGeneric.cpp +++ b/src/hoymiles/portParameters/portParametersGeneric.cpp @@ -29,7 +29,8 @@ std::pairparameterAddressOffset + portStartAddress, value); + int writeCount; + writeCount = modbus.modbus_write_register(this->parameterAddressOffset + portStartAddress, value); return *this; } diff --git a/src/main.cpp b/src/main.cpp index 4df0ebb..c8c3aa1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,9 +47,9 @@ int main(int argc, char **argv) { std::string shortNamesHelp{"Print short parameter names"}; hoymilesClient.add_flag("-s,--short", shortNames, shortNamesHelp)->group("Parameters"); - std::vector microinvertersToGet{}; - std::string microinvertersToGetHelp{"List of microinverters to fetch, delimited by ','; if omitted, all are fetched"}; - hoymilesClient.add_option>("-m,--microinverters", microinvertersToGet, microinvertersToGetHelp)->delimiter(',')->group("Microinverters"); + std::vector microinvertersToChoose{}; + std::string microinvertersToChooseHelp{"List of microinverters to work on, delimited by ','; if omitted, all are selected"}; + hoymilesClient.add_option>("-m,--microinverters", microinvertersToChoose, microinvertersToChooseHelp)->delimiter(',')->group("Microinverters"); bool microinvertersGetTodayProduction{false}; std::string microinvertersGetTodayProductionHelp{"Show today production for microinverters"}; @@ -63,6 +63,18 @@ int main(int argc, char **argv) { std::string ignoreNotConnectedHelp{"Ignore conn_error"}; hoymilesClient.add_flag("-I,--ignore_conn_error", ignoreNotConnected, ignoreNotConnectedHelp)->group("Debug"); + bool writeMode = false; + std::string writeModeHelp{"Write instead of read"}; + hoymilesClient.add_flag("-w,--write", writeMode, writeModeHelp)->group("Write"); + + uint16_t writeValue; + std::string writeValueHelp{"Value to write"}; + hoymilesClient.add_option("-V,--value", writeValue, writeModeHelp)->group("Write")->needs(hoymilesClient.get_option("-w")); + + std::string writeStatusName{}; + std::string writeStatusNameHelp{"Status to write"}; + hoymilesClient.add_option("-S,--status", writeStatusName, writeStatusName)->group("Write")->needs(hoymilesClient.get_option("-w")); + try { hoymilesClient.parse(argc, argv); } catch (const CLI::ParseError &e) { @@ -76,26 +88,33 @@ int main(int argc, char **argv) { std::cout << "DTU construction time: " << std::chrono::duration_cast(endTime - startTime).count() << "ms" << std::endl; std::cout << std::endl << std::endl; - while ((dtu.isConnected() || ignoreNotConnected) && (!parametersToGet.empty() || allParameters)) { + while (!writeMode && ((dtu.isConnected() || ignoreNotConnected) && (!parametersToGet.empty() || allParameters))) { time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); startTime = std::chrono::high_resolution_clock::now(); - dtu.updateMicroinverters(parametersToGet, allParameters, microinvertersToGet); + dtu.updateMicroinverters(parametersToGet, allParameters, microinvertersToChoose); endTime = std::chrono::high_resolution_clock::now(); std::cout << "Pass time: " << std::put_time(localtime(&now), "%F %T") << std::endl; std::cout << "DTU update time: " << std::chrono::duration_cast(endTime - startTime).count() << "ms" << std::endl; - dtu.printMicroinverters(parametersToGet, allParameters, microinvertersToGet, shortNames, microinvertersGetTodayProduction, microinvertersGetTotalProduction); + dtu.printMicroinverters(parametersToGet, allParameters, microinvertersToChoose, shortNames, microinvertersGetTodayProduction, microinvertersGetTotalProduction); std::cout << std::endl; - - std::vector> portsToLimitActivePower{std::pair(0, 69), std::pair(1, 38), std::pair(3, 3)}; - dtu.getMicroinverterBySerialNumber(138273312349).first->setStatus(portsToLimitActivePower, "limitActivePower"); } // if(dtu.modbusError()) { // std::cerr << dtu.modbusErrorMessage() << std::endl; // } + if(writeMode) { + std::cout << "Starting DTU write" << std::endl; + + startTime = std::chrono::high_resolution_clock::now(); + dtu.setStatusMicroinverters(writeValue, writeStatusName, microinvertersToChoose); + endTime = std::chrono::high_resolution_clock::now(); + + std::cout << "DTU write time: " << std::chrono::duration_cast(endTime - startTime).count() << "ms" << std::endl; + } + return 0; }