Compare commits

...

2 commits

Author SHA1 Message Date
c24e6c7d06 Ooga 2024-04-18 18:27:57 +02:00
79f8ee4944 pain 2024-04-18 18:27:31 +02:00
6 changed files with 149 additions and 14 deletions

View file

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

View file

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

View file

@ -11,7 +11,8 @@
#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) {
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;
if (modbus_connect(this->modbus) == -1) {
std::cerr << "NOT CONNECTED" << std::endl;
std::cerr << "[" << id << "] NOT_CONNECTED" << std::endl;
} else {
this->connected = true;
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; }
Dtu::~Dtu() {
@ -40,14 +59,32 @@ Dtu::~Dtu() {
}
void Dtu::populateMicroinverters() {
if(this->rtuId != -1) {
modbus_set_slave(this->modbus, this->rtuId);
}
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))) {
int registerCount;
registerCount = modbus_read_registers(this->modbus, portStartAddress, 19, registers);
int registerCount{-1};
int timesTried{0};
while (((timesTried < 3) && (lastSuccesful && registerCount == -1) && portStartAddress != addressToSkip)) {
registerCount = modbus_read_registers(this->modbus, portStartAddress, registersToRead, registers);
timesTried++;
}
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.setParametersFromMicroinverterArray(registers, 0);
@ -56,10 +93,23 @@ void Dtu::populateMicroinverters() {
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) {
if(this->rtuId != -1) {
modbus_set_slave(this->modbus, this->rtuId);
}
if (microinvertersToGet.empty()) {
std::vector<Microinverter>::iterator microinvertersIterator = this->microinverters.begin();
while (microinvertersIterator != this->microinverters.end()) {
@ -156,3 +209,38 @@ void Dtu::listOfMicroinverters() {
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 "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->startAddress = startAddress;
this->serialNumber = serialNumber;
@ -137,3 +137,29 @@ void Microinverter::setStatusWholeMicroinverter(uint16_t value, std::string stat
}
}
}
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() {
uint16_t registers[70];
uint16_t registers[2];
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();
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) {}
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) {}