2024-03-20 11:28:43 +01:00
|
|
|
#include <chrono>
|
2024-03-12 23:26:23 +01:00
|
|
|
#include <iostream>
|
2024-04-05 16:48:06 +02:00
|
|
|
#include <signal.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
2024-03-13 00:18:10 +01:00
|
|
|
#include <string>
|
2024-03-13 16:54:03 +01:00
|
|
|
#include <thread>
|
2024-03-20 11:28:43 +01:00
|
|
|
#include <vector>
|
2024-03-13 16:54:03 +01:00
|
|
|
|
2024-03-20 11:28:43 +01:00
|
|
|
#include "CLI11.hpp"
|
2024-03-13 00:18:10 +01:00
|
|
|
#include "modbus.h"
|
2024-03-20 11:28:43 +01:00
|
|
|
|
2024-03-16 21:15:15 +01:00
|
|
|
#include "dtu.h"
|
2024-03-12 23:26:23 +01:00
|
|
|
|
2024-03-20 16:15:07 +01:00
|
|
|
void sigHandler(int signal);
|
|
|
|
|
|
2024-03-20 11:28:43 +01:00
|
|
|
int main(int argc, char **argv) {
|
2024-03-20 16:15:07 +01:00
|
|
|
signal(SIGINT, sigHandler);
|
|
|
|
|
signal(SIGTERM, sigHandler);
|
|
|
|
|
signal(SIGABRT, sigHandler);
|
|
|
|
|
|
2024-04-09 12:21:21 +02:00
|
|
|
std::string version{"v2.3"};
|
2024-03-20 19:11:10 +01:00
|
|
|
std::cout << version << std::endl;
|
|
|
|
|
|
2024-03-20 11:28:43 +01:00
|
|
|
CLI::App hoymilesClient{"Client for DTU-Pro/DTU-ProS"};
|
|
|
|
|
|
2024-04-05 16:48:06 +02:00
|
|
|
hoymilesClient.set_version_flag("-v,--version", version);
|
|
|
|
|
|
2024-04-09 12:21:21 +02:00
|
|
|
std::string serialDeviceAddress{""};
|
|
|
|
|
std::string serialDeviceAddressHelp{"Serial device address"};
|
|
|
|
|
hoymilesClient.add_option<std::string>("-d,--serial_device_address", serialDeviceAddress, serialDeviceAddressHelp)->group("Serial");
|
|
|
|
|
|
|
|
|
|
bool rtuMode{false};
|
|
|
|
|
std::string rtuModeHelp{"Work in RTU mode"};
|
|
|
|
|
hoymilesClient.add_flag<bool>("-r,--rtu", rtuMode, rtuModeHelp)->needs(hoymilesClient.get_option("-d"))->group("Serial");
|
|
|
|
|
|
|
|
|
|
int rtuDeviceAddress{1};
|
|
|
|
|
std::string rtuDeviceAddressHelp{"Address on RS485 {default: }" + std::to_string(rtuDeviceAddress) + "}"};
|
|
|
|
|
hoymilesClient.add_option<int>("-a,--rt_device_address", rtuDeviceAddress, rtuDeviceAddressHelp)->group("Serial");
|
|
|
|
|
|
2024-03-20 11:28:43 +01:00
|
|
|
std::string ipAddress{"127.0.0.1"};
|
2024-04-09 12:21:21 +02:00
|
|
|
std::string ipAddressHelp{"Ipv4 address of DTU {default: " + ipAddress + "}"};
|
|
|
|
|
hoymilesClient.add_option<std::string>("-i,--ip_address", ipAddress, ipAddressHelp)->group("Networking");
|
|
|
|
|
|
|
|
|
|
bool tcpMode{false};
|
|
|
|
|
std::string tcpModeHelp{"Work in Ipv4 mode"};
|
|
|
|
|
hoymilesClient.add_flag<bool>("-t,--tcp", tcpMode, tcpModeHelp)->needs(hoymilesClient.get_option("-i"))->group("Networking");
|
2024-03-20 11:28:43 +01:00
|
|
|
|
|
|
|
|
int port{502};
|
|
|
|
|
std::string portHelp{"Port of DTU {default: " + std::to_string(port) + "}"};
|
2024-03-20 19:55:36 +01:00
|
|
|
hoymilesClient.add_option<int>("-p,--port", port, portHelp)->group("Networking");
|
2024-03-20 11:28:43 +01:00
|
|
|
|
|
|
|
|
std::vector<std::string> parametersToGet{};
|
2024-04-05 16:48:06 +02:00
|
|
|
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]"};
|
2024-03-20 19:55:36 +01:00
|
|
|
hoymilesClient.add_option<std::vector<std::string>>("-P,--parameters", parametersToGet, parametersToGetHelp)->delimiter(',')->group("Parameters");
|
2024-03-20 11:28:43 +01:00
|
|
|
|
2024-04-09 12:21:21 +02:00
|
|
|
bool allParameters{false};
|
2024-03-20 11:28:43 +01:00
|
|
|
std::string allParametersHelp{"Fetch all parameters"};
|
2024-04-09 12:21:21 +02:00
|
|
|
hoymilesClient.add_flag<bool>("-A,--all_parameters", allParameters, allParametersHelp)->group("Parameters");
|
2024-03-20 11:28:43 +01:00
|
|
|
|
2024-04-09 12:21:21 +02:00
|
|
|
bool shortNames{false};
|
2024-03-20 22:48:59 +01:00
|
|
|
std::string shortNamesHelp{"Print short parameter names"};
|
|
|
|
|
hoymilesClient.add_flag<bool>("-s,--short", shortNames, shortNamesHelp)->group("Parameters");
|
2024-03-20 11:28:43 +01:00
|
|
|
|
2024-04-09 12:21:21 +02:00
|
|
|
bool getMicroinverters{false};
|
|
|
|
|
std::string getMicroinvertersHelp{"Print all microinverters instead of getting parameters"};
|
|
|
|
|
hoymilesClient.add_flag<bool>("-M,--get_microinverters", getMicroinverters, getMicroinvertersHelp)->group("Microinverters");
|
|
|
|
|
|
2024-04-06 16:29:02 +02:00
|
|
|
std::vector<long long> microinvertersToChoose{};
|
|
|
|
|
std::string microinvertersToChooseHelp{"List of microinverters to work on, delimited by ','; if omitted, all are selected"};
|
|
|
|
|
hoymilesClient.add_option<std::vector<long long>>("-m,--microinverters", microinvertersToChoose, microinvertersToChooseHelp)->delimiter(',')->group("Microinverters");
|
2024-03-20 19:55:36 +01:00
|
|
|
|
2024-03-28 19:44:54 +01:00
|
|
|
bool microinvertersGetTodayProduction{false};
|
2024-03-20 22:48:59 +01:00
|
|
|
std::string microinvertersGetTodayProductionHelp{"Show today production for microinverters"};
|
2024-04-09 12:21:21 +02:00
|
|
|
hoymilesClient.add_flag<bool>("-D,--today_production", microinvertersGetTodayProduction, microinvertersGetTodayProductionHelp)->group("Microinverters");
|
2024-03-20 22:48:59 +01:00
|
|
|
|
2024-03-28 19:44:54 +01:00
|
|
|
bool microinvertersGetTotalProduction{false};
|
2024-03-20 22:48:59 +01:00
|
|
|
std::string microinvertersGetTotalProductionHelp{"Show total production for microinverters"};
|
|
|
|
|
hoymilesClient.add_flag<bool>("-T,--total_production", microinvertersGetTotalProduction, microinvertersGetTotalProductionHelp)->group("Microinverters");
|
2024-03-20 20:17:15 +01:00
|
|
|
|
2024-03-20 19:55:36 +01:00
|
|
|
bool ignoreNotConnected = false;
|
|
|
|
|
std::string ignoreNotConnectedHelp{"Ignore conn_error"};
|
|
|
|
|
hoymilesClient.add_flag<bool>("-I,--ignore_conn_error", ignoreNotConnected, ignoreNotConnectedHelp)->group("Debug");
|
2024-03-20 14:40:02 +01:00
|
|
|
|
2024-04-06 16:29:02 +02:00
|
|
|
bool writeMode = false;
|
|
|
|
|
std::string writeModeHelp{"Write instead of read"};
|
|
|
|
|
hoymilesClient.add_flag<bool>("-w,--write", writeMode, writeModeHelp)->group("Write");
|
|
|
|
|
|
|
|
|
|
uint16_t writeValue;
|
|
|
|
|
std::string writeValueHelp{"Value to write"};
|
|
|
|
|
hoymilesClient.add_option<uint16_t>("-V,--value", writeValue, writeModeHelp)->group("Write")->needs(hoymilesClient.get_option("-w"));
|
|
|
|
|
|
|
|
|
|
std::string writeStatusName{};
|
|
|
|
|
std::string writeStatusNameHelp{"Status to write"};
|
|
|
|
|
hoymilesClient.add_option<std::string>("-S,--status", writeStatusName, writeStatusName)->group("Write")->needs(hoymilesClient.get_option("-w"));
|
|
|
|
|
|
2024-03-20 14:40:02 +01:00
|
|
|
try {
|
|
|
|
|
hoymilesClient.parse(argc, argv);
|
|
|
|
|
} catch (const CLI::ParseError &e) {
|
|
|
|
|
return hoymilesClient.exit(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::cout << "Mapping out DTU" << std::endl;
|
2024-03-20 11:28:43 +01:00
|
|
|
auto startTime = std::chrono::high_resolution_clock::now();
|
2024-04-09 12:21:21 +02:00
|
|
|
std::string address;
|
|
|
|
|
int id;
|
|
|
|
|
if (tcpMode) {
|
|
|
|
|
address = ipAddress;
|
|
|
|
|
id = port;
|
|
|
|
|
}
|
|
|
|
|
if (rtuMode) {
|
|
|
|
|
address = serialDeviceAddress;
|
|
|
|
|
id = rtuDeviceAddress;
|
|
|
|
|
}
|
|
|
|
|
Dtu dtu{address.c_str(), id, rtuMode, tcpMode};
|
2024-03-20 11:28:43 +01:00
|
|
|
auto endTime = std::chrono::high_resolution_clock::now();
|
|
|
|
|
std::cout << "DTU construction time: " << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() << "ms" << std::endl;
|
2024-04-05 16:48:06 +02:00
|
|
|
std::cout << std::endl << std::endl;
|
2024-03-12 23:26:23 +01:00
|
|
|
|
2024-04-09 12:21:21 +02:00
|
|
|
while ((!writeMode && !getMicroinverters) && (!dtu.empty() && ((dtu.isConnected() || ignoreNotConnected) && (!parametersToGet.empty() || allParameters)))) {
|
2024-04-05 16:48:06 +02:00
|
|
|
time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
|
|
|
|
|
2024-03-20 14:40:02 +01:00
|
|
|
startTime = std::chrono::high_resolution_clock::now();
|
2024-04-06 16:29:02 +02:00
|
|
|
dtu.updateMicroinverters(parametersToGet, allParameters, microinvertersToChoose);
|
2024-03-20 14:40:02 +01:00
|
|
|
endTime = std::chrono::high_resolution_clock::now();
|
2024-04-06 00:32:49 +02:00
|
|
|
|
2024-04-05 16:48:06 +02:00
|
|
|
std::cout << "Pass time: " << std::put_time(localtime(&now), "%F %T") << std::endl;
|
2024-03-20 14:40:02 +01:00
|
|
|
std::cout << "DTU update time: " << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() << "ms" << std::endl;
|
|
|
|
|
|
2024-04-06 16:29:02 +02:00
|
|
|
dtu.printMicroinverters(parametersToGet, allParameters, microinvertersToChoose, shortNames, microinvertersGetTodayProduction, microinvertersGetTotalProduction);
|
2024-03-20 14:40:02 +01:00
|
|
|
std::cout << std::endl;
|
2024-03-20 11:28:43 +01:00
|
|
|
}
|
2024-03-28 19:44:54 +01:00
|
|
|
// if(dtu.modbusError()) {
|
|
|
|
|
// std::cerr << dtu.modbusErrorMessage() << std::endl;
|
|
|
|
|
// }
|
2024-03-15 11:46:44 +01:00
|
|
|
|
2024-04-09 12:21:21 +02:00
|
|
|
if(getMicroinverters) {
|
|
|
|
|
dtu.listOfMicroinverters();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (writeMode) {
|
2024-04-06 16:29:02 +02:00
|
|
|
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<std::chrono::milliseconds>(endTime - startTime).count() << "ms" << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-20 11:28:43 +01:00
|
|
|
return 0;
|
2024-03-20 16:15:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sigHandler(int signal) {
|
2024-03-20 19:39:25 +01:00
|
|
|
std::cerr << "Interrupted\n";
|
2024-03-20 16:15:07 +01:00
|
|
|
exit(0);
|
2024-03-12 23:26:23 +01:00
|
|
|
}
|