Relase 2.5 #21
7 changed files with 151 additions and 16 deletions
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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> ¶metersToGet, bool allParameters, std::vector<long long> µinvertersToGet) {
|
void Dtu::updateMicroinverters(std::vector<std::string> ¶metersToGet, bool allParameters, std::vector<long long> µinvertersToGet) {
|
||||||
|
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()) {
|
||||||
|
|
@ -156,3 +209,38 @@ void Dtu::listOfMicroinverters() {
|
||||||
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); }
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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) {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue