From 32d9dfff98ca9a3e36bc712559dc1c749e3d9817 Mon Sep 17 00:00:00 2001 From: trabus322 Date: Fri, 5 Apr 2024 16:48:06 +0200 Subject: [PATCH 1/4] MAde some small corrections, fixed up some values, preparing for writing --- .../portParameters/portParametersGeneric.h | 9 ++++-- src/hoymiles/dtu.cpp | 4 +-- src/hoymiles/microinverter.cpp | 2 +- src/hoymiles/port.cpp | 3 +- .../portParameters/portParameters.cpp | 32 +++++++++---------- .../portParameters/portParametersGeneric.cpp | 9 ++++-- src/main.cpp | 19 +++++++---- 7 files changed, 46 insertions(+), 32 deletions(-) diff --git a/inc/hoymiles/portParameters/portParametersGeneric.h b/inc/hoymiles/portParameters/portParametersGeneric.h index b91952b..b9ba714 100644 --- a/inc/hoymiles/portParameters/portParametersGeneric.h +++ b/inc/hoymiles/portParameters/portParametersGeneric.h @@ -15,8 +15,11 @@ class PortParameter { std::string unit; + bool r; + bool w; + public: - PortParameter(std::string name, std::string shortName, std::string unit, uint16_t parameterAddressOffset, int registerSize); + PortParameter(std::string name, std::string shortName, std::string unit, bool r, bool w, uint16_t parameterAddressOffset, int registerSize); virtual ~PortParameter(); @@ -51,7 +54,7 @@ class PortParameterFloat : public PortParameter { int decimalPlaces; public: - PortParameterFloat(std::string name, std::string shortName, std::string unit, int decimalPlaces, uint16_t parameterAddressOffset, int registerSize); + PortParameterFloat(std::string name, std::string shortName, std::string unit, bool r, bool w, int decimalPlaces, uint16_t parameterAddressOffset, int registerSize); std::string getOutputValue(); @@ -62,7 +65,7 @@ class PortParameterInt : public PortParameter { protected: public: - PortParameterInt(std::string name, std::string shortName, std::string unit, uint16_t parameterAddressOffset, int registerSize); + PortParameterInt(std::string name, std::string shortName, std::string unit, bool r, bool w, uint16_t parameterAddressOffset, int registerSize); std::string getOutputValue(); diff --git a/src/hoymiles/dtu.cpp b/src/hoymiles/dtu.cpp index 96cdd5c..4f2f9bc 100644 --- a/src/hoymiles/dtu.cpp +++ b/src/hoymiles/dtu.cpp @@ -111,10 +111,10 @@ void Dtu::printMicroinverters(std::vector ¶metersToGet, bool al std::cout << " " << "Microinverter: " << microinverterPair.first->serialNumber << std::endl; std::cout << " " << "Microinverter Data Age: " << microinverterPair.first->age << std::endl; if (printTodayProduction) { - std::cout << " " << "TodayProduction: " << microinverterPair.first->getTodayProduction() << std::endl; + std::cout << " " << "TodayProduction: " << microinverterPair.first->getTodayProduction() << "Wh" << std::endl; } if (printTotalProduction) { - std::cout << " " << "TotalProduction: " << microinverterPair.first->getTotalProduction() << std::endl; + std::cout << " " << "TotalProduction: " << microinverterPair.first->getTotalProduction() << "Wh" << std::endl; } microinverterPair.first->printPorts(parametersToGet, allParameters, shortNames); std::cout << std::endl; diff --git a/src/hoymiles/microinverter.cpp b/src/hoymiles/microinverter.cpp index 993599e..c36cc40 100644 --- a/src/hoymiles/microinverter.cpp +++ b/src/hoymiles/microinverter.cpp @@ -43,7 +43,7 @@ void Microinverter::updateParameters(std::vector ¶metersToGet, } for (int i{0}; i < portsToRead; i++) { - this->ports.at(i).setParametersFromMicroinverterArray(registers, i * 0x0019); + this->ports.at(i + portsRead).setParametersFromMicroinverterArray(registers, i * 0x0019); } portsRead += portsToRead; diff --git a/src/hoymiles/port.cpp b/src/hoymiles/port.cpp index 7b1a518..069acf6 100644 --- a/src/hoymiles/port.cpp +++ b/src/hoymiles/port.cpp @@ -80,7 +80,7 @@ void Port::fixCurrent() { if (this->getParameterByName("pvPower").first->getValue().first.f > this->getParameterByName("pvVoltage").first->getValue().first.f * this->getParameterByName("pvCurrentMI").first->getValue().first.f) { this->parameters.erase(std::find(this->parameters.begin(), this->parameters.end(), this->getParameterByName("pvCurrentHM").first)); } else { - this->parameters.erase(std::find(this->parameters.begin(), this->parameters.end(), this->getParameterByName("pvCurrentM").first)); + this->parameters.erase(std::find(this->parameters.begin(), this->parameters.end(), this->getParameterByName("pvCurrentMI").first)); } this->currentFixed = true; } @@ -129,6 +129,7 @@ void Port::setParametersFromMicroinverterArray(uint16_t *registers, int addressO parametersIterator->get()->setValueFromRegisters(registers, addressOffset); parametersIterator++; } + this->fixCurrent(); } void Port::printParameters(std::vector ¶metersToGet, bool allParameters, bool shortNames) { diff --git a/src/hoymiles/portParameters/portParameters.cpp b/src/hoymiles/portParameters/portParameters.cpp index 39237cb..478f6b8 100644 --- a/src/hoymiles/portParameters/portParameters.cpp +++ b/src/hoymiles/portParameters/portParameters.cpp @@ -5,43 +5,43 @@ #include "portParameters.h" -PortParameterMicroinverterSerialNumber::PortParameterMicroinverterSerialNumber() : PortParameterInt("microinverterSerialNumber", "mSN", "", 0x0001, 3) {} +PortParameterMicroinverterSerialNumber::PortParameterMicroinverterSerialNumber() : PortParameterInt("microinverterSerialNumber", "mSN", "", false, false, 0x0001, 3) {} void PortParameterMicroinverterSerialNumber::setValueFromRegisters(uint16_t *registers, int addressOffset) { std::string readValueString = ""; for (int i{0}; i < this->registerSize; i++) { std::stringstream readValueStringStream; - readValueStringStream << std::hex << (int) ((registers[addressOffset + this->parameterAddressOffset + i] & 0xff00) > 8); + readValueStringStream << std::hex << (int) ((registers[addressOffset + this->parameterAddressOffset + i] & 0xff00) >> 8); readValueStringStream << std::hex << (int) (registers[addressOffset + this->parameterAddressOffset + i] & 0x00ff); readValueString.append(readValueStringStream.str()); } this->value.i = std::stoll(readValueString); } -PortParameterPortNumber::PortParameterPortNumber() : PortParameterInt("portNumber", "pN", "", 0x0004, 1) {} +PortParameterPortNumber::PortParameterPortNumber() : PortParameterInt("portNumber", "pN", "", false, false, 0x0004, 1) {} -PortParameterPvVoltage::PortParameterPvVoltage() : PortParameterFloat("pvVoltage", "pvU", "V", 1, 0x0005, 1) {} +PortParameterPvVoltage::PortParameterPvVoltage() : PortParameterFloat("pvVoltage", "pvU", "V", false, false, 1, 0x0005, 1) {} -PortParameterPvCurrentMi::PortParameterPvCurrentMi() : PortParameterFloat("pvCurrentMI", "pvIMI", "A", 1, 0x0006, 1) {} +PortParameterPvCurrentMi::PortParameterPvCurrentMi() : PortParameterFloat("pvCurrentMI", "pvIMI", "A", false, false, 1, 0x0006, 1) {} -PortParameterPvCurrentHm::PortParameterPvCurrentHm() : PortParameterFloat("pvCurrentHM", "pvIHM", "A", 2, 0x0006, 1) {} +PortParameterPvCurrentHm::PortParameterPvCurrentHm() : PortParameterFloat("pvCurrentHM", "pvIHM", "A", false, false, 2, 0x0006, 1) {} -PortParameterGridVoltage::PortParameterGridVoltage() : PortParameterFloat("gridVoltage", "gU", "V", 1, 0x0007, 1) {} +PortParameterGridVoltage::PortParameterGridVoltage() : PortParameterFloat("gridVoltage", "gU", "V", false, false, 1, 0x0007, 1) {} -PortParameterGridFrequency::PortParameterGridFrequency() : PortParameterFloat("gridFrequency", "gF", "Hz", 2, 0x0008, 1) {} +PortParameterGridFrequency::PortParameterGridFrequency() : PortParameterFloat("gridFrequency", "gF", "Hz", false, false, 2, 0x0008, 1) {} -PortParameterPvPower::PortParameterPvPower() : PortParameterFloat("pvPower", "pvP", "W", 1, 0x0009, 1) {} +PortParameterPvPower::PortParameterPvPower() : PortParameterFloat("pvPower", "pvP", "W", false, false, 1, 0x0009, 1) {} -PortParameterTodayProduction::PortParameterTodayProduction() : PortParameterInt("todayProduction", "tdP", "Wh", 0x000A, 1) {} +PortParameterTodayProduction::PortParameterTodayProduction() : PortParameterInt("todayProduction", "tdP", "Wh", false, false, 0x000A, 1) {} -PortParameterTotalProduction::PortParameterTotalProduction() : PortParameterInt("totalProduction", "ttP", "Wh", 0x000B, 2) {} +PortParameterTotalProduction::PortParameterTotalProduction() : PortParameterInt("totalProduction", "ttP", "Wh", false, false, 0x000B, 2) {} -PortParameterTemperature::PortParameterTemperature() : PortParameterFloat("temperature", "t", "C", 1, 0x000D, 1) {} +PortParameterTemperature::PortParameterTemperature() : PortParameterFloat("temperature", "t", "C", false, false, 1, 0x000D, 1) {} -PortParameterOperatingStatus::PortParameterOperatingStatus() : PortParameterInt("operatingStatus", "oS", "", 0x000e, 1) {} +PortParameterOperatingStatus::PortParameterOperatingStatus() : PortParameterInt("operatingStatus", "oS", "", false, false, 0x000e, 1) {} -PortParameterAlarmCode::PortParameterAlarmCode() : PortParameterInt("alarmCode", "aC", "", 0x000f, 1) {} +PortParameterAlarmCode::PortParameterAlarmCode() : PortParameterInt("alarmCode", "aC", "", false, false, 0x000f, 1) {} -PortParameterAlarmCount::PortParameterAlarmCount() : PortParameterInt("alarmCount", "aCnt", "", 0x0010, 1) {} +PortParameterAlarmCount::PortParameterAlarmCount() : PortParameterInt("alarmCount", "aCnt", "", false, false, 0x0010, 1) {} -PortParameterLinkStatus::PortParameterLinkStatus() : PortParameterInt("linkStatus", "lS", "", 0x011, 1) {} \ No newline at end of file +PortParameterLinkStatus::PortParameterLinkStatus() : PortParameterInt("linkStatus", "lS", "", false, false, 0x011, 1) {} \ No newline at end of file diff --git a/src/hoymiles/portParameters/portParametersGeneric.cpp b/src/hoymiles/portParameters/portParametersGeneric.cpp index bdea96f..c8b0a81 100644 --- a/src/hoymiles/portParameters/portParametersGeneric.cpp +++ b/src/hoymiles/portParameters/portParametersGeneric.cpp @@ -8,11 +8,14 @@ #include "portParametersGeneric.h" -PortParameter::PortParameter(std::string name, std::string shortName, std::string unit, uint16_t parameterAddressOffset, int registerSize) { +PortParameter::PortParameter(std::string name, std::string shortName, std::string unit, bool r, bool w, uint16_t parameterAddressOffset, int registerSize) { this->name = name; this->shortName = shortName; this->unit = unit; + this->r = r; + this->w = w; + this->parameterAddressOffset = parameterAddressOffset; this->registerSize = registerSize; @@ -47,7 +50,7 @@ std::string PortParameter::getOutputValue() { // } // } -PortParameterFloat::PortParameterFloat(std::string name, std::string shortName, std::string unit, int decimalPlaces, uint16_t parameterAddressOffset, int registerSize) : PortParameter(name, shortName, unit, parameterAddressOffset, registerSize) { +PortParameterFloat::PortParameterFloat(std::string name, std::string shortName, std::string unit, bool r, bool w, int decimalPlaces, uint16_t parameterAddressOffset, int registerSize) : PortParameter(name, shortName, unit, r, w, parameterAddressOffset, registerSize) { this->decimalPlaces = decimalPlaces; this->valueType = Float; @@ -71,7 +74,7 @@ std::string PortParameterFloat::getOutputValue() { return valueStringStream.str().append(this->unit.c_str()); } -PortParameterInt::PortParameterInt(std::string name, std::string shortName, std::string unit, uint16_t parameterAddressOffset, int registerSize) : PortParameter(name, shortName, unit, parameterAddressOffset, registerSize) { +PortParameterInt::PortParameterInt(std::string name, std::string shortName, std::string unit, bool r, bool w, uint16_t parameterAddressOffset, int registerSize) : PortParameter(name, shortName, unit, r, w, parameterAddressOffset, registerSize) { this->valueType = Int; this->value.i = 0; diff --git a/src/main.cpp b/src/main.cpp index 0b22ab6..5052c0d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,11 @@ #include #include +#include +#include +#include #include #include #include -#include -#include -#include #include "CLI11.hpp" #include "modbus.h" @@ -19,11 +19,13 @@ int main(int argc, char **argv) { signal(SIGTERM, sigHandler); signal(SIGABRT, sigHandler); - std::string version{"v2.1"}; + std::string version{"v2.2w"}; std::cout << version << std::endl; CLI::App hoymilesClient{"Client for DTU-Pro/DTU-ProS"}; + hoymilesClient.set_version_flag("-v,--version", version); + std::string ipAddress{"127.0.0.1"}; std::string ipAddressHelp{"ipv4 address of DTU {default: " + ipAddress + "}"}; hoymilesClient.add_option("-i,--ip_address", ipAddress, ipAddressHelp)->required()->group("Networking"); @@ -33,7 +35,8 @@ int main(int argc, char **argv) { hoymilesClient.add_option("-p,--port", port, portHelp)->group("Networking"); std::vector parametersToGet{}; - std::string parametersToGetHelp{"List of parameters to fetch, delimited by ','; possible parameters:\n - pvVoltage [pvU]\n - pvCurrentMI [pvIMI]\n - pvCurrentHM [pvIHM]\n - gridVoltage [gU]\n - gridFrequency [gF]\n - pvPower [gP]\n - todayProduction [tdP]\n - totalProduction [ttP]\n - temperature [t]\n - operatingStatus [oS]\n - alarmCode [aC]\n - alarmCount [aCnt]\n - linkStatus [lS]"}; + std::string parametersToGetHelp{"List of parameters to fetch, delimited by ','; possible parameters:\n - pvVoltage [pvU]\n - pvCurrentMI [pvIMI]\n - pvCurrentHM [pvIHM]\n - gridVoltage [gU]\n - gridFrequency [gF]\n - pvPower [gP]\n - " + "todayProduction [tdP]\n - totalProduction [ttP]\n - temperature [t]\n - operatingStatus [oS]\n - alarmCode [aC]\n - alarmCount [aCnt]\n - linkStatus [lS]"}; hoymilesClient.add_option>("-P,--parameters", parametersToGet, parametersToGetHelp)->delimiter(',')->group("Parameters"); bool allParameters = false; @@ -60,7 +63,6 @@ int main(int argc, char **argv) { std::string ignoreNotConnectedHelp{"Ignore conn_error"}; hoymilesClient.add_flag("-I,--ignore_conn_error", ignoreNotConnected, ignoreNotConnectedHelp)->group("Debug"); - try { hoymilesClient.parse(argc, argv); } catch (const CLI::ParseError &e) { @@ -72,11 +74,16 @@ int main(int argc, char **argv) { Dtu dtu{ipAddress.c_str(), port}; auto endTime = std::chrono::high_resolution_clock::now(); 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)) { + 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); 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); From 34313ef4bc871c92707cde3e45f06dbb1965e2b3 Mon Sep 17 00:00:00 2001 From: trabus322 Date: Sat, 6 Apr 2024 00:32:49 +0200 Subject: [PATCH 2/4] sadge but more worky --- inc/hoymiles/dtu.h | 4 +- inc/hoymiles/microinverter.h | 6 +++ inc/hoymiles/port.h | 13 +++++ inc/hoymiles/portParameters/portParameters.h | 12 ++++- .../portParameters/portParametersGeneric.h | 8 +-- .../sunspecParameters/sunspecParameters.h | 2 +- .../sunspecParametersGeneric.h | 20 +++---- src/hoymiles/dtu.cpp | 1 + src/hoymiles/microinverter.cpp | 37 +++++++++++++ src/hoymiles/port.cpp | 53 ++++++++++++++++--- .../portParameters/portParameters.cpp | 36 +++++++------ .../portParameters/portParametersGeneric.cpp | 29 +++------- src/hoymiles/sunspec.cpp | 2 +- .../sunspecParameters/sunspecParameters.cpp | 2 +- .../sunspecParametersGeneric.cpp | 4 +- src/main.cpp | 5 +- 16 files changed, 169 insertions(+), 65 deletions(-) diff --git a/inc/hoymiles/dtu.h b/inc/hoymiles/dtu.h index b4a3ccd..135e4a4 100644 --- a/inc/hoymiles/dtu.h +++ b/inc/hoymiles/dtu.h @@ -16,11 +16,11 @@ class Dtu { void populateMicroinverters(); - std::pair getMicroinverterBySerialNumber(long long serialNumber); - public: Dtu(const char *ip_address, int port); + std::pair getMicroinverterBySerialNumber(long long serialNumber); + bool isConnected(); bool modbusError(); diff --git a/inc/hoymiles/microinverter.h b/inc/hoymiles/microinverter.h index 5e817cb..1172db8 100644 --- a/inc/hoymiles/microinverter.h +++ b/inc/hoymiles/microinverter.h @@ -17,6 +17,8 @@ class Microinverter { int startAddress; + int statusStartAddress; + public: Microinverter(std::shared_ptr modbus, int startAddress, long long serialNumber); @@ -30,11 +32,15 @@ class Microinverter { void updateParameters(std::vector ¶metersToGet, bool allParameters); + void updateStatusParameters(); + void printPorts(std::vector ¶metersToGet, bool allParameters, bool shortNames); long long getTodayProduction(); long long getTotalProduction(); + + void setStatus(std::vector> portsToSet, std::string statusName); }; #endif \ No newline at end of file diff --git a/inc/hoymiles/port.h b/inc/hoymiles/port.h index 6cb1d62..df37dd5 100644 --- a/inc/hoymiles/port.h +++ b/inc/hoymiles/port.h @@ -6,6 +6,7 @@ #include #include "portParametersGeneric.h" +#include "portParameters.h" #include "modbus.h" class Port { @@ -22,15 +23,27 @@ class Port { int portStartAddress; + int statusPortStartAddress; + std::vector> parameters; + std::vector> statusParameters; + std::pair, bool> getParameterByName(std::string name); + std::pair, bool> getStatusByName(std::string name); + // void updateParameters(std::vector ¶metersToGet, bool allParameters); void setParametersFromMicroinverterArray(uint16_t *registers, int addressOffset); + void setStatusesFromMicroinverterArray(uint16_t *registers, int addressOffset); + void printParameters(std::vector ¶metersToGet, bool allParameters, bool shortNames); + + void turnOff(class modbus &modbus); + + bool isOff(class modbus &modbus); }; #endif \ No newline at end of file diff --git a/inc/hoymiles/portParameters/portParameters.h b/inc/hoymiles/portParameters/portParameters.h index 93d1a8b..cd15028 100644 --- a/inc/hoymiles/portParameters/portParameters.h +++ b/inc/hoymiles/portParameters/portParameters.h @@ -5,7 +5,7 @@ class PortParameterMicroinverterSerialNumber : public PortParameterInt { private: - void setValueFromRegisters(uint16_t *registers, int addressOffset); + void getValueFromRegisters(uint16_t *registers, int addressOffset); public: PortParameterMicroinverterSerialNumber(); @@ -81,4 +81,14 @@ class PortParameterLinkStatus : public PortParameterInt { PortParameterLinkStatus(); }; +class PortParameterOnOff : public PortParameterInt { + public: + PortParameterOnOff(); +}; + +class PortParameterLimitActivePower : public PortParameterInt { + public: + PortParameterLimitActivePower(); +}; + #endif \ No newline at end of file diff --git a/inc/hoymiles/portParameters/portParametersGeneric.h b/inc/hoymiles/portParameters/portParametersGeneric.h index b9ba714..23f3856 100644 --- a/inc/hoymiles/portParameters/portParametersGeneric.h +++ b/inc/hoymiles/portParameters/portParametersGeneric.h @@ -42,9 +42,11 @@ class PortParameter { std::pair getValue(); + PortParameter& writeValue(uint16_t value, class modbus& modbus, int portStartAddress); + virtual std::string getOutputValue(); - virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); + virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); // void updateValue(std::shared_ptr modubs, uint16_t portStartAddress); }; @@ -58,7 +60,7 @@ class PortParameterFloat : public PortParameter { std::string getOutputValue(); - virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); + virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); }; class PortParameterInt : public PortParameter { @@ -69,7 +71,7 @@ class PortParameterInt : public PortParameter { std::string getOutputValue(); - virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); + virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); }; #endif \ No newline at end of file diff --git a/inc/hoymiles/sunspecParameters/sunspecParameters.h b/inc/hoymiles/sunspecParameters/sunspecParameters.h index 745d47c..cdf4bed 100644 --- a/inc/hoymiles/sunspecParameters/sunspecParameters.h +++ b/inc/hoymiles/sunspecParameters/sunspecParameters.h @@ -9,7 +9,7 @@ class SunspecParameterManufacturer : public SunspecParameterString32 { public: SunspecParameterManufacturer(); - void setValueFromRegisters(uint16_t *registers, int addressOffset); + void getValueFromRegisters(uint16_t *registers, int addressOffset); }; #endif \ No newline at end of file diff --git a/inc/hoymiles/sunspecParameters/sunspecParametersGeneric.h b/inc/hoymiles/sunspecParameters/sunspecParametersGeneric.h index ab916a6..aba5e8d 100644 --- a/inc/hoymiles/sunspecParameters/sunspecParametersGeneric.h +++ b/inc/hoymiles/sunspecParameters/sunspecParametersGeneric.h @@ -33,7 +33,7 @@ class SunspecParameter { public: - virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); + virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); std::pair getValue(); }; @@ -44,7 +44,7 @@ class SunspecParameter { // public: // SunspecParameterUint32(std::string name, int registerAddressOffset, int registerSize); -// virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); // }; // class SunspecParameterUint16 : public SunspecParameter { @@ -53,7 +53,7 @@ class SunspecParameter { // public: // SunspecParameterUint16(std::string name, int registerAddressOffset, int registerSize); -// virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); // }; class SunspecParameterString32 : public SunspecParameter { @@ -63,7 +63,7 @@ class SunspecParameterString32 : public SunspecParameter { public: SunspecParameterString32(std::string name, int registerAddressOffset, int registerSize); - virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); + virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); }; // class SunspecParameterString16 : public SunspecParameter { @@ -73,7 +73,7 @@ class SunspecParameterString32 : public SunspecParameter { // public: // SunspecParameterString16(std::string name, int registerAddressOffset, int registerSize); -// virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); // }; // class SunspecParameterSunssf : public SunspecParameter { @@ -82,7 +82,7 @@ class SunspecParameterString32 : public SunspecParameter { // public: // SunspecParameterSunssf(std::string name, int registerAddressOffset, int registerSize); -// virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); // }; // class SunspecParameterInt16 : public SunspecParameter { @@ -91,7 +91,7 @@ class SunspecParameterString32 : public SunspecParameter { // public: // SunspecParameterInt16(std::string name, int registerAddressOffset, int registerSize); -// virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); // }; // class SunspecParameterAcc32 : public SunspecParameter { @@ -100,7 +100,7 @@ class SunspecParameterString32 : public SunspecParameter { // public: // SunspecParameterAcc32(std::string name, int registerAddressOffset, int registerSize); -// virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); // }; // class SunspecParameterFloat32 : public SunspecParameter { @@ -109,7 +109,7 @@ class SunspecParameterString32 : public SunspecParameter { // public: // SunspecParameterFloat32(std::string name, int registerAddressOffset, int registerSize); -// virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); // }; // class SunspecParameterEnum16 : public SunspecParameter { @@ -118,7 +118,7 @@ class SunspecParameterString32 : public SunspecParameter { // public: // SunspecParameterEnum16(std::string name, int registerAddressOffset, int registerSize); -// virtual void setValueFromRegisters(uint16_t *registers, int addressOffset); +// virtual void getValueFromRegisters(uint16_t *registers, int addressOffset); // }; #endif \ No newline at end of file diff --git a/src/hoymiles/dtu.cpp b/src/hoymiles/dtu.cpp index 4f2f9bc..ec51a3c 100644 --- a/src/hoymiles/dtu.cpp +++ b/src/hoymiles/dtu.cpp @@ -90,6 +90,7 @@ void Dtu::updateMicroinverters(std::vector ¶metersToGet, bool a std::pair microinverterPair = this->getMicroinverterBySerialNumber(*microinvertersToGetIterator); if (microinverterPair.second) { microinverterPair.first->updateParameters(parametersToGet, allParameters); + microinverterPair.first->updateStatusParameters(); } microinvertersToGetIterator++; } diff --git a/src/hoymiles/microinverter.cpp b/src/hoymiles/microinverter.cpp index c36cc40..858b11a 100644 --- a/src/hoymiles/microinverter.cpp +++ b/src/hoymiles/microinverter.cpp @@ -13,6 +13,8 @@ Microinverter::Microinverter(std::shared_ptr modbus, int startAddr this->startAddress = startAddress; this->serialNumber = serialNumber; + this->statusStartAddress = (((this->startAddress - 0x4000) / 0x0019) * 6) + 0xd006; + this->age = 0; } @@ -50,6 +52,33 @@ void Microinverter::updateParameters(std::vector ¶metersToGet, } } +void Microinverter::updateStatusParameters() { + int portsRead = 0; + while (portsRead < this->ports.size()) { + int portsToRead = 0; + while (portsToRead * 6 < (10 - 6) && (portsToRead + portsRead) < this->ports.size()) { + portsToRead++; + } + + int registersToRead = (portsToRead * 6); + uint16_t registers[registersToRead]; + + int registerCount; + registerCount = this->modbus.get()->modbus_read_holding_registers(this->statusStartAddress + (portsRead * 6), registersToRead, registers); + + if (registerCount != 0) { + this->age++; + return; + } + + for (int i{0}; i < portsToRead; i++) { + this->ports.at(i + portsRead).setStatusesFromMicroinverterArray(registers, i * 6); + } + + portsRead += portsToRead; + } +} + void Microinverter::printPorts(std::vector ¶metersToGet, bool allParameters, bool shortNames) { std::vector::iterator portsIterator = this->ports.begin(); while (portsIterator != this->ports.end()) { @@ -81,4 +110,12 @@ long long Microinverter::getTotalProduction() { } return result; +} + +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); + portsToSetIterator++; + } } \ No newline at end of file diff --git a/src/hoymiles/port.cpp b/src/hoymiles/port.cpp index 069acf6..6a9c7d0 100644 --- a/src/hoymiles/port.cpp +++ b/src/hoymiles/port.cpp @@ -12,6 +12,8 @@ Port::Port(int portStartAddress) { this->portStartAddress = portStartAddress; + this->statusPortStartAddress = (((this->portStartAddress - 0x4000) / 0x0019) * 6) + 0xd006; + this->currentFixed = false; this->populateParameters(); @@ -47,6 +49,11 @@ void Port::populateParameters() { this->parameters.push_back(std::make_shared()); this->parameters.push_back(std::make_shared()); + + + this->statusParameters.push_back(std::make_shared()); + + this->statusParameters.push_back(std::make_shared()); } std::pair, bool> Port::getParameterByName(std::string name) { @@ -65,6 +72,22 @@ std::pair, bool> Port::getParameterByName(std::st return result; } +std::pair, bool> Port::getStatusByName(std::string name) { + std::pair, bool> result; + result.second = false; + + std::vector>::iterator parametersIterator = this->statusParameters.begin(); + while (parametersIterator != this->statusParameters.end() && !result.second) { + if (parametersIterator->get()->name == name) { + result.first = *parametersIterator; + result.second = true; + } + parametersIterator++; + } + + return result; +} + void Port::fixCurrent() { if (this->currentFixed) { return; @@ -125,13 +148,21 @@ void Port::fixCurrent() { void Port::setParametersFromMicroinverterArray(uint16_t *registers, int addressOffset) { std::vector>::iterator parametersIterator = this->parameters.begin(); - while(parametersIterator != this->parameters.end()) { - parametersIterator->get()->setValueFromRegisters(registers, addressOffset); + while (parametersIterator != this->parameters.end()) { + parametersIterator->get()->getValueFromRegisters(registers, addressOffset); parametersIterator++; } this->fixCurrent(); } +void Port::setStatusesFromMicroinverterArray(uint16_t *registers, int addressOffset) { + std::vector>::iterator parametersIterator = this->statusParameters.begin(); + while (parametersIterator != this->statusParameters.end()) { + parametersIterator->get()->getValueFromRegisters(registers, addressOffset); + parametersIterator++; + } +} + void Port::printParameters(std::vector ¶metersToGet, bool allParameters, bool shortNames) { if (allParameters && parametersToGet.size() < this->parameters.size()) { std::vector>::iterator parametersIterator = this->parameters.begin(); @@ -150,7 +181,7 @@ void Port::printParameters(std::vector ¶metersToGet, bool allPa } while (parametersToGetIterator != parametersToGet.end()) { - if(*parametersToGetIterator == "microinverterSerialNumber") { + if (*parametersToGetIterator == "microinverterSerialNumber") { parametersToGetIterator++; continue; } @@ -159,14 +190,24 @@ void Port::printParameters(std::vector ¶metersToGet, bool allPa parameterPair = this->getParameterByName(*parametersToGetIterator); if (parameterPair.second) { std::cout << " "; - if(shortNames) { + if (shortNames) { std::cout << parameterPair.first->shortName; - } - else { + } else { std::cout << parameterPair.first->name; } std::cout << ": " << parameterPair.first->getOutputValue() << " |"; } parametersToGetIterator++; } +} + +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) { + return true; + } + else { + return false; + } } \ No newline at end of file diff --git a/src/hoymiles/portParameters/portParameters.cpp b/src/hoymiles/portParameters/portParameters.cpp index 478f6b8..1b404ec 100644 --- a/src/hoymiles/portParameters/portParameters.cpp +++ b/src/hoymiles/portParameters/portParameters.cpp @@ -5,9 +5,9 @@ #include "portParameters.h" -PortParameterMicroinverterSerialNumber::PortParameterMicroinverterSerialNumber() : PortParameterInt("microinverterSerialNumber", "mSN", "", false, false, 0x0001, 3) {} +PortParameterMicroinverterSerialNumber::PortParameterMicroinverterSerialNumber() : PortParameterInt("microinverterSerialNumber", "mSN", "", true, false, 0x0001, 3) {} -void PortParameterMicroinverterSerialNumber::setValueFromRegisters(uint16_t *registers, int addressOffset) { +void PortParameterMicroinverterSerialNumber::getValueFromRegisters(uint16_t *registers, int addressOffset) { std::string readValueString = ""; for (int i{0}; i < this->registerSize; i++) { std::stringstream readValueStringStream; @@ -18,30 +18,34 @@ void PortParameterMicroinverterSerialNumber::setValueFromRegisters(uint16_t *reg this->value.i = std::stoll(readValueString); } -PortParameterPortNumber::PortParameterPortNumber() : PortParameterInt("portNumber", "pN", "", false, false, 0x0004, 1) {} +PortParameterPortNumber::PortParameterPortNumber() : PortParameterInt("portNumber", "pN", "", true, false, 0x0004, 1) {} -PortParameterPvVoltage::PortParameterPvVoltage() : PortParameterFloat("pvVoltage", "pvU", "V", false, false, 1, 0x0005, 1) {} +PortParameterPvVoltage::PortParameterPvVoltage() : PortParameterFloat("pvVoltage", "pvU", "V", true, false, 1, 0x0005, 1) {} -PortParameterPvCurrentMi::PortParameterPvCurrentMi() : PortParameterFloat("pvCurrentMI", "pvIMI", "A", false, false, 1, 0x0006, 1) {} +PortParameterPvCurrentMi::PortParameterPvCurrentMi() : PortParameterFloat("pvCurrentMI", "pvIMI", "A", true, false, 1, 0x0006, 1) {} -PortParameterPvCurrentHm::PortParameterPvCurrentHm() : PortParameterFloat("pvCurrentHM", "pvIHM", "A", false, false, 2, 0x0006, 1) {} +PortParameterPvCurrentHm::PortParameterPvCurrentHm() : PortParameterFloat("pvCurrentHM", "pvIHM", "A", true, false, 2, 0x0006, 1) {} -PortParameterGridVoltage::PortParameterGridVoltage() : PortParameterFloat("gridVoltage", "gU", "V", false, false, 1, 0x0007, 1) {} +PortParameterGridVoltage::PortParameterGridVoltage() : PortParameterFloat("gridVoltage", "gU", "V", true, false, 1, 0x0007, 1) {} -PortParameterGridFrequency::PortParameterGridFrequency() : PortParameterFloat("gridFrequency", "gF", "Hz", false, false, 2, 0x0008, 1) {} +PortParameterGridFrequency::PortParameterGridFrequency() : PortParameterFloat("gridFrequency", "gF", "Hz", true, false, 2, 0x0008, 1) {} -PortParameterPvPower::PortParameterPvPower() : PortParameterFloat("pvPower", "pvP", "W", false, false, 1, 0x0009, 1) {} +PortParameterPvPower::PortParameterPvPower() : PortParameterFloat("pvPower", "pvP", "W", true, false, 1, 0x0009, 1) {} -PortParameterTodayProduction::PortParameterTodayProduction() : PortParameterInt("todayProduction", "tdP", "Wh", false, false, 0x000A, 1) {} +PortParameterTodayProduction::PortParameterTodayProduction() : PortParameterInt("todayProduction", "tdP", "Wh", true, false, 0x000A, 1) {} -PortParameterTotalProduction::PortParameterTotalProduction() : PortParameterInt("totalProduction", "ttP", "Wh", false, false, 0x000B, 2) {} +PortParameterTotalProduction::PortParameterTotalProduction() : PortParameterInt("totalProduction", "ttP", "Wh", true, false, 0x000B, 2) {} -PortParameterTemperature::PortParameterTemperature() : PortParameterFloat("temperature", "t", "C", false, false, 1, 0x000D, 1) {} +PortParameterTemperature::PortParameterTemperature() : PortParameterFloat("temperature", "t", "C", true, false, 1, 0x000D, 1) {} -PortParameterOperatingStatus::PortParameterOperatingStatus() : PortParameterInt("operatingStatus", "oS", "", false, false, 0x000e, 1) {} +PortParameterOperatingStatus::PortParameterOperatingStatus() : PortParameterInt("operatingStatus", "oS", "", true, false, 0x000e, 1) {} -PortParameterAlarmCode::PortParameterAlarmCode() : PortParameterInt("alarmCode", "aC", "", false, false, 0x000f, 1) {} +PortParameterAlarmCode::PortParameterAlarmCode() : PortParameterInt("alarmCode", "aC", "", true, false, 0x000f, 1) {} -PortParameterAlarmCount::PortParameterAlarmCount() : PortParameterInt("alarmCount", "aCnt", "", false, false, 0x0010, 1) {} +PortParameterAlarmCount::PortParameterAlarmCount() : PortParameterInt("alarmCount", "aCnt", "", true, false, 0x0010, 1) {} -PortParameterLinkStatus::PortParameterLinkStatus() : PortParameterInt("linkStatus", "lS", "", false, false, 0x011, 1) {} \ No newline at end of file +PortParameterLinkStatus::PortParameterLinkStatus() : PortParameterInt("linkStatus", "lS", "", true, false, 0x011, 1) {} + +PortParameterOnOff::PortParameterOnOff() : PortParameterInt("onOff", "of", "", true, true, 0x0000, 1) {} + +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 c8b0a81..502d148 100644 --- a/src/hoymiles/portParameters/portParametersGeneric.cpp +++ b/src/hoymiles/portParameters/portParametersGeneric.cpp @@ -18,38 +18,25 @@ PortParameter::PortParameter(std::string name, std::string shortName, std::strin this->parameterAddressOffset = parameterAddressOffset; this->registerSize = registerSize; - - // this->age = 0; } PortParameter::~PortParameter() {} -void PortParameter::setValueFromRegisters(uint16_t *readArray, int portOffset) {} +void PortParameter::getValueFromRegisters(uint16_t *readArray, int portOffset) {} std::pair PortParameter::getValue() { return std::pair(this->value, this->valueType); } +PortParameter& PortParameter::writeValue(uint16_t value, class modbus& modbus, int portStartAddress) { + modbus.modbus_write_register(this->parameterAddressOffset + portStartAddress, value); + return *this; +} + std::string PortParameter::getOutputValue() { return "yeet"; } -// void PortParameter::updateValue(std::shared_ptr modbus, uint16_t portStartAddress) { -// uint16_t readArray[this->registerSize]; -// int registerCount; - -// registerCount = modbus.get()->modbus_read_holding_registers(portStartAddress + this->parameterAddressOffset, this->registerSize, readArray); - -// if(registerCount != 0){ -// this->age++; -// } -// else{ -// registerCount = this->registerSize; -// this->setValueFromRegisters(readArray, registerCount); -// this->age = 0; -// } -// } - PortParameterFloat::PortParameterFloat(std::string name, std::string shortName, std::string unit, bool r, bool w, int decimalPlaces, uint16_t parameterAddressOffset, int registerSize) : PortParameter(name, shortName, unit, r, w, parameterAddressOffset, registerSize) { this->decimalPlaces = decimalPlaces; @@ -58,7 +45,7 @@ PortParameterFloat::PortParameterFloat(std::string name, std::string shortName, this->value.f = 0; } -void PortParameterFloat::setValueFromRegisters(uint16_t *registers, int addressOffset) { +void PortParameterFloat::getValueFromRegisters(uint16_t *registers, int addressOffset) { std::string readValueString{""}; for(int i{0}; iregisterSize; i++) { std::stringstream readValueStringStream; @@ -80,7 +67,7 @@ PortParameterInt::PortParameterInt(std::string name, std::string shortName, std: this->value.i = 0; } -void PortParameterInt::setValueFromRegisters(uint16_t *registers, int addressOffset) { +void PortParameterInt::getValueFromRegisters(uint16_t *registers, int addressOffset) { std::string readValueString{""}; for (int i{0}; i < this->registerSize; i++) { std::stringstream readValueStringStream; diff --git a/src/hoymiles/sunspec.cpp b/src/hoymiles/sunspec.cpp index d50cd50..3a94b0c 100644 --- a/src/hoymiles/sunspec.cpp +++ b/src/hoymiles/sunspec.cpp @@ -23,7 +23,7 @@ void Sunspec::setValues() { std::vector>::iterator parametersIterator = this->parameters.begin(); while(parametersIterator != this->parameters.end()) { - parametersIterator->get()->setValueFromRegisters(registers, 0); + parametersIterator->get()->getValueFromRegisters(registers, 0); parametersIterator++; } } diff --git a/src/hoymiles/sunspecParameters/sunspecParameters.cpp b/src/hoymiles/sunspecParameters/sunspecParameters.cpp index 1312b08..1b68bdd 100644 --- a/src/hoymiles/sunspecParameters/sunspecParameters.cpp +++ b/src/hoymiles/sunspecParameters/sunspecParameters.cpp @@ -8,7 +8,7 @@ SunspecParameterManufacturer::SunspecParameterManufacturer() : SunspecParameterS this->valueType = string32; } -void SunspecParameterManufacturer::setValueFromRegisters(uint16_t *registers, int addressOffset) { +void SunspecParameterManufacturer::getValueFromRegisters(uint16_t *registers, int addressOffset) { std::string readValue; for(int i{0}; iregisterSize; i++) { diff --git a/src/hoymiles/sunspecParameters/sunspecParametersGeneric.cpp b/src/hoymiles/sunspecParameters/sunspecParametersGeneric.cpp index c825428..93186e5 100644 --- a/src/hoymiles/sunspecParameters/sunspecParametersGeneric.cpp +++ b/src/hoymiles/sunspecParameters/sunspecParametersGeneric.cpp @@ -8,10 +8,10 @@ SunspecParameter::SunspecParameter(std::string name, int registerAddressOffset, this->registerSize = registerSize; } -void SunspecParameter::setValueFromRegisters(uint16_t *registers, int addressOffset) {} +void SunspecParameter::getValueFromRegisters(uint16_t *registers, int addressOffset) {} std::pair SunspecParameter::getValue() {} SunspecParameterString32::SunspecParameterString32(std::string name, int registerAddressOffset, int registerSize) : SunspecParameter(name, registerAddressOffset, registerSize) {} -void SunspecParameterString32::setValueFromRegisters(uint16_t *registers, int addressOffset) {} \ No newline at end of file +void SunspecParameterString32::getValueFromRegisters(uint16_t *registers, int addressOffset) {} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5052c0d..4df0ebb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -82,12 +82,15 @@ int main(int argc, char **argv) { startTime = std::chrono::high_resolution_clock::now(); dtu.updateMicroinverters(parametersToGet, allParameters, microinvertersToGet); 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); 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; From 0b29fb881d77f3dcd57cd429e83fd731b9a2ac84 Mon Sep 17 00:00:00 2001 From: trabus322 Date: Sat, 6 Apr 2024 16:29:02 +0200 Subject: [PATCH 3/4] Writing is working! --- inc/hoymiles/dtu.h | 2 + inc/hoymiles/microinverter.h | 2 + src/hoymiles/dtu.cpp | 19 ++++++++++ src/hoymiles/microinverter.cpp | 22 ++++++++++- src/hoymiles/port.cpp | 18 +++++++-- .../portParameters/portParameters.cpp | 2 +- .../portParameters/portParametersGeneric.cpp | 3 +- src/main.cpp | 37 ++++++++++++++----- 8 files changed, 88 insertions(+), 17 deletions(-) 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; } From 266dcefdfd2e9f3f1d181f3a8ea298ec74fda291 Mon Sep 17 00:00:00 2001 From: trabus322 Date: Sat, 6 Apr 2024 19:29:23 +0200 Subject: [PATCH 4/4] Doing some prevention --- inc/hoymiles/dtu.h | 2 ++ src/hoymiles/dtu.cpp | 4 ++++ src/main.cpp | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/inc/hoymiles/dtu.h b/inc/hoymiles/dtu.h index b5f98bc..bf11234 100644 --- a/inc/hoymiles/dtu.h +++ b/inc/hoymiles/dtu.h @@ -33,6 +33,8 @@ class Dtu { void setStatusMicroinverters(uint16_t value, std::string statusName, std::vector& microinvertersToSet); + bool empty(); + ~Dtu(); }; diff --git a/src/hoymiles/dtu.cpp b/src/hoymiles/dtu.cpp index 0f7ce54..85859fa 100644 --- a/src/hoymiles/dtu.cpp +++ b/src/hoymiles/dtu.cpp @@ -141,4 +141,8 @@ void Dtu::setStatusMicroinverters(uint16_t value, std::string statusName, std::v } microinvertersToSetIterator++; } +} + +bool Dtu::empty() { + return this->microinverters.empty(); } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index c8c3aa1..3c461e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -88,7 +88,7 @@ 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 (!writeMode && ((dtu.isConnected() || ignoreNotConnected) && (!parametersToGet.empty() || allParameters))) { + while (!writeMode && (!dtu.empty() && ((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();