Compare commits

..

4 commits

7 changed files with 151 additions and 16 deletions

View file

@ -14,6 +14,10 @@ class Dtu {
std::vector<Microinverter> microinverters; std::vector<Microinverter> microinverters;
Port dtuPort;
int rtuId;
bool connected; bool connected;
void populateMicroinverters(); void populateMicroinverters();
@ -21,6 +25,8 @@ class Dtu {
public: public:
Dtu(const char *address, int id, bool rtu, bool tcp); Dtu(const char *address, int id, bool rtu, bool tcp);
Dtu(modbus_t *modbus, int id);
std::pair<Microinverter *, bool> getMicroinverterBySerialNumber(long long serialNumber); std::pair<Microinverter *, bool> getMicroinverterBySerialNumber(long long serialNumber);
bool isConnected(); bool isConnected();
@ -35,6 +41,15 @@ class Dtu {
void listOfMicroinverters(); void listOfMicroinverters();
float getCurrentPower();
int getCurrentOnOff();
void turnOffMicroinverters();
void turnOnMicroinverters();
void limitMicroinverters(uint16_t limit);
~Dtu(); ~Dtu();
}; };

View file

@ -13,7 +13,7 @@ class Microinverter {
private: private:
modbus_t *modbus; modbus_t *modbus;
Sunspec sunspec; // Sunspec sunspec;
int startAddress; int startAddress;
@ -43,6 +43,10 @@ class Microinverter {
void setStatus(std::vector<std::pair<int, uint16_t>> portsToSet, std::string statusName); void setStatus(std::vector<std::pair<int, uint16_t>> portsToSet, std::string statusName);
void setStatusWholeMicroinverter(uint16_t value, std::string statusName); void setStatusWholeMicroinverter(uint16_t value, std::string statusName);
float getCurrentPower();
int getCurrentOnOff();
}; };
#endif #endif

View file

@ -11,7 +11,8 @@
#include "portParameters.h" #include "portParameters.h"
Dtu::Dtu(const char *address, int id, bool rtu, bool tcp) { Dtu::Dtu(const char *address, int id, bool rtu, bool tcp) : dtuPort(0) {
dtuPort.statusPortStartAddress = 0xd000;
if (tcp) { if (tcp) {
this->modbus = modbus_new_tcp(address, id); this->modbus = modbus_new_tcp(address, id);
} }
@ -22,7 +23,7 @@ Dtu::Dtu(const char *address, int id, bool rtu, bool tcp) {
this->connected = false; this->connected = false;
if (modbus_connect(this->modbus) == -1) { if (modbus_connect(this->modbus) == -1) {
std::cerr << "NOT CONNECTED" << std::endl; std::cerr << "[" << id << "] NOT_CONNECTED" << std::endl;
} else { } else {
this->connected = true; this->connected = true;
if (rtu) { if (rtu) {
@ -32,6 +33,24 @@ Dtu::Dtu(const char *address, int id, bool rtu, bool tcp) {
} }
} }
Dtu::Dtu(modbus_t *modbus, int id = -1) : dtuPort(0) {
dtuPort.statusPortStartAddress = 0xd000;
this->modbus = modbus;
this->rtuId = id;
this->connected = false;
if (modbus_connect(this->modbus) == -1) {
std::cerr << "[" << id << "] NOT_CONNECTED" << std::endl;
} else {
this->connected = true;
if (id != -1) {
modbus_set_slave(this->modbus, rtuId);
}
this->populateMicroinverters();
}
}
bool Dtu::isConnected() { return this->connected; } bool Dtu::isConnected() { return this->connected; }
Dtu::~Dtu() { Dtu::~Dtu() {
@ -40,14 +59,32 @@ Dtu::~Dtu() {
} }
void Dtu::populateMicroinverters() { void Dtu::populateMicroinverters() {
if(this->rtuId != -1) {
modbus_set_slave(this->modbus, this->rtuId);
}
int portStartAddress = 0x4000; int portStartAddress = 0x4000;
uint16_t registers[19]; int registersToRead{19};
uint16_t registers[registersToRead];
bool lastSuccesful{true};
int addressToSkip{-1};
while (portStartAddress <= (0x4000 + (0x0019 * 99))) { while (portStartAddress <= (0x4000 + (0x0019 * 99))) {
int registerCount; int registerCount{-1};
registerCount = modbus_read_registers(this->modbus, portStartAddress, 19, registers); int timesTried{0};
while (((timesTried < 3) && (lastSuccesful && registerCount == -1) && portStartAddress != addressToSkip)) {
registerCount = modbus_read_registers(this->modbus, portStartAddress, registersToRead, registers);
timesTried++;
}
portStartAddress += 0x0019; portStartAddress += 0x0019;
if (registers[0] == 12) { if ((registers[0] == 12 && registerCount != -1) && portStartAddress != addressToSkip) {
if (!lastSuccesful) {
addressToSkip = portStartAddress;
portStartAddress -= 2 * 0x0019;
}
lastSuccesful = true;
Port port{portStartAddress}; Port port{portStartAddress};
port.setParametersFromMicroinverterArray(registers, 0); port.setParametersFromMicroinverterArray(registers, 0);
@ -56,10 +93,23 @@ void Dtu::populateMicroinverters() {
this->microinverters.push_back(microinverter); this->microinverters.push_back(microinverter);
} }
this->getMicroinverterBySerialNumber(port.getParameterByName("microinverterSerialNumber").first.get()->getValue().first.i).first->ports.push_back(port); Microinverter *microinverter = this->getMicroinverterBySerialNumber(port.getParameterByName("microinverterSerialNumber").first.get()->getValue().first.i).first;
std::vector<Port>::iterator portsIterator = microinverter->ports.begin();
bool valueExists{false};
while (portsIterator != microinverter->ports.end() && !valueExists) {
if (portsIterator->getParameterByName("portNumber").first.get()->getValue().first.i == port.getParameterByName("portNumber").first.get()->getValue().first.i) {
valueExists = true;
}
portsIterator++;
}
if (!valueExists) {
microinverter->ports.push_back(port);
}
} else {
lastSuccesful = false;
} }
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(20));
} }
} }
@ -76,6 +126,9 @@ std::pair<Microinverter *, bool> Dtu::getMicroinverterBySerialNumber(long long s
} }
void Dtu::updateMicroinverters(std::vector<std::string> &parametersToGet, bool allParameters, std::vector<long long> &microinvertersToGet) { void Dtu::updateMicroinverters(std::vector<std::string> &parametersToGet, bool allParameters, std::vector<long long> &microinvertersToGet) {
if(this->rtuId != -1) {
modbus_set_slave(this->modbus, this->rtuId);
}
if (microinvertersToGet.empty()) { if (microinvertersToGet.empty()) {
std::vector<Microinverter>::iterator microinvertersIterator = this->microinverters.begin(); std::vector<Microinverter>::iterator microinvertersIterator = this->microinverters.begin();
while (microinvertersIterator != this->microinverters.end()) { while (microinvertersIterator != this->microinverters.end()) {
@ -155,4 +208,39 @@ void Dtu::listOfMicroinverters() {
std::cout << " " << microinvertersIterator->serialNumber << std::endl; std::cout << " " << microinvertersIterator->serialNumber << std::endl;
microinvertersIterator++; microinvertersIterator++;
} }
} }
float Dtu::getCurrentPower() {
std::vector<Microinverter>::iterator microinvertersIterator = this->microinverters.begin();
float currentPower{0};
while (microinvertersIterator != this->microinverters.end()) {
currentPower += microinvertersIterator->getCurrentPower();
microinvertersIterator++;
}
return currentPower;
}
int Dtu::getCurrentOnOff() {
if(this->microinverters.size() == 0) {
return 0;
}
std::vector<Microinverter>::iterator microinvertersIterator = this->microinverters.begin();
int currentOn{0};
while(microinvertersIterator != this->microinverters.end()) {
currentOn += microinvertersIterator->getCurrentOnOff();
microinvertersIterator++;
}
float balance = currentOn / this->microinverters.size();
if(balance >= 0.5) {
return 1;
}
else {
return 0;
}
}
void Dtu::turnOffMicroinverters() { this->dtuPort.getStatusByName("onOff").first.get()->writeValue(0, this->modbus, this->dtuPort.statusPortStartAddress); }
void Dtu::turnOnMicroinverters() { this->dtuPort.getStatusByName("onOff").first.get()->writeValue(1, this->modbus, this->dtuPort.statusPortStartAddress); }
void Dtu::limitMicroinverters(uint16_t limit) { this->dtuPort.getStatusByName("limitActivePower").first.get()->writeValue(limit, this->modbus, this->dtuPort.statusPortStartAddress); }

View file

@ -8,7 +8,7 @@
#include "port.h" #include "port.h"
#include "sunspec.h" #include "sunspec.h"
Microinverter::Microinverter(modbus_t *modbus, int startAddress, long long serialNumber) : sunspec(40000, modbus) { Microinverter::Microinverter(modbus_t *modbus, int startAddress, long long serialNumber) {
this->modbus = modbus; this->modbus = modbus;
this->startAddress = startAddress; this->startAddress = startAddress;
this->serialNumber = serialNumber; this->serialNumber = serialNumber;
@ -136,4 +136,30 @@ void Microinverter::setStatusWholeMicroinverter(uint16_t value, std::string stat
this->ports.begin()->getStatusByName(statusName).first.get()->writeValue(value, this->modbus, this->ports.begin()->statusPortStartAddress); this->ports.begin()->getStatusByName(statusName).first.get()->writeValue(value, this->modbus, this->ports.begin()->statusPortStartAddress);
} }
} }
}
float Microinverter::getCurrentPower() {
std::vector<Port>::iterator portsIterator = this->ports.begin();
float currentPower{0};
while(portsIterator != this->ports.end()) {
currentPower += portsIterator->getParameterByName("pvPower").first.get()->getValue().first.f;
portsIterator++;
}
return currentPower;
}
int Microinverter::getCurrentOnOff() {
std::vector<Port>::iterator portsIterator = this->ports.begin();
int currentOn{0};
while(portsIterator != this->ports.end()) {
currentOn += portsIterator->getStatusByName("onOff").first.get()->getValue().first.i;
portsIterator++;
}
float balance = currentOn / this->ports.size();
if(balance >= 0.5) {
return 1;
}
else {
return 0;
}
} }

View file

@ -16,10 +16,10 @@ Sunspec::Sunspec(int address, modbus_t *modbus) {
} }
void Sunspec::setValues() { void Sunspec::setValues() {
uint16_t registers[70]; uint16_t registers[2];
int registerCount; int registerCount;
registerCount = modbus_read_registers(this->modbus, this->sunspecAddress, 70, registers); registerCount = modbus_read_registers(this->modbus, this->sunspecAddress, 2, registers);
std::vector<std::shared_ptr<SunspecParameter>>::iterator parametersIterator = this->parameters.begin(); std::vector<std::shared_ptr<SunspecParameter>>::iterator parametersIterator = this->parameters.begin();
while(parametersIterator != this->parameters.end()) { while(parametersIterator != this->parameters.end()) {

View file

@ -10,7 +10,9 @@ SunspecParameter::SunspecParameter(std::string name, int registerAddressOffset,
void SunspecParameter::getValueFromRegisters(uint16_t *registers, int addressOffset) {} void SunspecParameter::getValueFromRegisters(uint16_t *registers, int addressOffset) {}
std::pair<SunspecParameter::SunspecValue, SunspecParameter::SunspecValueType> SunspecParameter::getValue() {} std::pair<SunspecParameter::SunspecValue, SunspecParameter::SunspecValueType> SunspecParameter::getValue() {
return {this->value, this->valueType};
}
SunspecParameterString32::SunspecParameterString32(std::string name, int registerAddressOffset, int registerSize) : SunspecParameter(name, registerAddressOffset, registerSize) {} SunspecParameterString32::SunspecParameterString32(std::string name, int registerAddressOffset, int registerSize) : SunspecParameter(name, registerAddressOffset, registerSize) {}

View file

@ -19,7 +19,7 @@ int main(int argc, char **argv) {
signal(SIGTERM, sigHandler); signal(SIGTERM, sigHandler);
signal(SIGABRT, sigHandler); signal(SIGABRT, sigHandler);
std::string version{"v2.4h"}; std::string version{"v2.5"};
std::cout << version << std::endl; std::cout << version << std::endl;
CLI::App hoymilesClient{"Client for DTU-Pro/DTU-ProS"}; CLI::App hoymilesClient{"Client for DTU-Pro/DTU-ProS"};
@ -154,4 +154,4 @@ int main(int argc, char **argv) {
void sigHandler(int signal) { void sigHandler(int signal) {
std::cerr << "Interrupted\n"; std::cerr << "Interrupted\n";
exit(0); exit(0);
} }