Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
58a43d4648 | ||
![]() |
25fdaac582 | ||
![]() |
5d9e828903 | ||
![]() |
f95f3fe3d0 | ||
![]() |
2cfe71d323 | ||
![]() |
523d10d386 | ||
![]() |
6df6012edf | ||
![]() |
9ba7a470ad | ||
![]() |
750297157d | ||
![]() |
d86ca1e596 | ||
![]() |
6003eaa675 | ||
![]() |
d74a2a3e78 | ||
![]() |
69596fa400 | ||
![]() |
0d7e12ce55 | ||
![]() |
46c308bc14 |
@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.0)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
add_compile_options(-Wno-psabi)
|
||||
|
||||
project(inverter-tools VERSION 1.4.0)
|
||||
project(inverter-tools VERSION 1.4.99)
|
||||
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX /usr/local/bin)
|
||||
@ -97,10 +97,3 @@ target_link_libraries(testserial ${LIBSERIALPORT_LIBRARY})
|
||||
target_include_directories(testserial PRIVATE
|
||||
${LIBSERIALPORT_INCLUDE_DIR}
|
||||
third_party/hexdump)
|
||||
|
||||
|
||||
# inverterd
|
||||
#add_executable(inverterd
|
||||
# src/inverterd.cc)
|
||||
#target_link_libraries(inverterd ${HIDAPI_LIBRARY} ${LIBSERIALPORT_LIBRARY} m)
|
||||
# TODO install
|
||||
|
@ -20,9 +20,10 @@ is planned.
|
||||
- HIDAPI
|
||||
- libserialport
|
||||
|
||||
## Supported devices
|
||||
## Tested devices
|
||||
|
||||
As of time of writing, only InfiniSolar V 5KW was tested.
|
||||
- [InfiniSolar V 5KW](https://ekoproekt-energo.ru/infinisolar-v-5k-48)
|
||||
- [Crown Micro Elego 6KW](https://coollineenergy.com/product/crown-micro-elego-6kw-solar-hybrid-inverter/)
|
||||
|
||||
## Supported interfaces
|
||||
|
||||
@ -40,6 +41,8 @@ for all possible options and commands.
|
||||
for querying inverterd server.
|
||||
- [inverter-bot](https://github.com/gch1p/inverter-bot) - Telegram bot that uses inverterd
|
||||
for querying data.
|
||||
- [inverter-http-proxy](https://github.com/gch1p/inverter-http-proxy) - HTTP
|
||||
"frontend" for inverterd
|
||||
|
||||
## License
|
||||
|
||||
|
@ -24,6 +24,7 @@ enum {
|
||||
LO_DEVICE_ERROR_LIMIT,
|
||||
LO_USB_VENDOR_ID,
|
||||
LO_USB_DEVICE_ID,
|
||||
LO_USB_PATH,
|
||||
LO_SERIAL_NAME,
|
||||
LO_SERIAL_BAUD_RATE,
|
||||
LO_SERIAL_DATA_BITS,
|
||||
|
@ -127,6 +127,10 @@ public:
|
||||
explicit Table(Format format, std::vector<TableItem<T>> v)
|
||||
: Formattable(format), v_(v) {}
|
||||
|
||||
void push(TableItem<T> item) {
|
||||
v_.push_back(item);
|
||||
}
|
||||
|
||||
std::ostream& writeSimpleTable(std::ostream& os) const override {
|
||||
for (const auto& item: v_) {
|
||||
os << item.key << " ";
|
||||
|
@ -78,6 +78,9 @@ static void usage(const char* progname) {
|
||||
"USB device options:\n"
|
||||
" --usb-vendor-id <ID>: Vendor ID (default: " << std::setw(4) << voltronic::USBDevice::VENDOR_ID << ")\n"
|
||||
" --usb-device-id <ID>: Device ID (default: " << std::setw(4) << voltronic::USBDevice::PRODUCT_ID << ")\n"
|
||||
"\n"
|
||||
" Alternatively, you can specify device path (e.g., /dev/hidraw0):\n"
|
||||
" --usb-path <PATH>: Device path\n"
|
||||
"\n";
|
||||
std::cout.flags(f);
|
||||
std::cout <<
|
||||
@ -95,7 +98,7 @@ static void usage(const char* progname) {
|
||||
" get-year-generated <yyyy>\n"
|
||||
" get-month-generated <yyyy> <mm>\n"
|
||||
" get-day-generated <yyyy> <mm> <dd>\n"
|
||||
" get-series-number\n"
|
||||
" get-serial-number\n"
|
||||
" get-cpu-version\n"
|
||||
" get-rated\n"
|
||||
" get-status\n"
|
||||
@ -109,55 +112,55 @@ static void usage(const char* progname) {
|
||||
" get-errors\n"
|
||||
" get-flags\n"
|
||||
" get-rated-defaults\n"
|
||||
" get-allowed-charging-currents\n"
|
||||
" get-allowed-ac-charging-currents\n"
|
||||
" get-ac-charging-time\n"
|
||||
" get-ac-loads-supply-time\n"
|
||||
" set-loads-supply 0|1\n"
|
||||
" get-allowed-charge-currents\n"
|
||||
" get-allowed-ac-charge-currents\n"
|
||||
" get-ac-charge-time\n"
|
||||
" get-ac-supply-time\n"
|
||||
" set-ac-supply 0|1\n"
|
||||
" set-flag <flag> 0|1\n"
|
||||
" set-rated-defaults\n"
|
||||
" set-max-charging-current <id> <amps>\n"
|
||||
" id: Parallel machine ID (use 0 for single model)\n"
|
||||
" amps: Use get-allowed-charging-currents\n"
|
||||
" set-max-charge-current <id> <amps>\n"
|
||||
" id: Parallel machine ID\n"
|
||||
" amps: Use get-allowed-charge-currents\n"
|
||||
" to see a list of allowed values.\n"
|
||||
"\n"
|
||||
" set-max-ac-charging-current <id> <amps>\n"
|
||||
" id: Parallel machine ID (use 0 for single model)\n"
|
||||
" amps: Use get-allowed-ac-charging-currents\n"
|
||||
" set-max-ac-charge-current <id> <amps>\n"
|
||||
" id: Parallel machine ID\n"
|
||||
" amps: Use get-allowed-ac-charge-currents\n"
|
||||
" to see a list of allowed values.\n"
|
||||
"\n"
|
||||
" set-max-charge-voltage <cv> <fv>\n"
|
||||
" cv: Constant voltage (48.0 ~ 58.4)\n"
|
||||
" fv: Float voltage (48.0 ~ 58.4)\n"
|
||||
"\n"
|
||||
" set-ac-output-freq 50|60\n"
|
||||
" set-max-charging-voltage <cv> <fv>\n"
|
||||
" cv: Constant voltage (48.0 ~ 58.4).\n"
|
||||
" fv: Float voltage (48.0 ~ 58.4).\n"
|
||||
"\n"
|
||||
" set-ac-output-voltage <v>\n"
|
||||
" v: " << p18::ac_output_rated_voltages << "\n"
|
||||
" v: " << p18::ac_output_voltages << "\n"
|
||||
"\n"
|
||||
" set-output-source-priority SUB|SBU\n"
|
||||
" 'SUB' means " << p18::OutputSourcePriority::SolarUtilityBattery << "\n"
|
||||
" 'SBU' means " << p18::OutputSourcePriority::SolarBatteryUtility << "\n"
|
||||
"\n"
|
||||
" set-charging-thresholds <cv> <dv>\n"
|
||||
" Set battery re-charging and re-discharging voltages when\n"
|
||||
" utility is available.\n"
|
||||
" set-charge-thresholds <cv> <dv>\n"
|
||||
" Set battery re-charge and re-discharge voltages when\n"
|
||||
" grid is connected.\n"
|
||||
"\n"
|
||||
" cv: re-charging voltage\n"
|
||||
" For 12 V unit: " << p18::bat_ac_recharging_voltages_12v << "\n"
|
||||
" For 24 V unit: " << p18::bat_ac_recharging_voltages_24v << "\n"
|
||||
" For 48 V unit: " << p18::bat_ac_recharging_voltages_48v << "\n"
|
||||
" cv: re-charge voltage\n"
|
||||
" For 12 V unit: " << p18::bat_ac_recharge_voltages_12v << "\n"
|
||||
" For 24 V unit: " << p18::bat_ac_recharge_voltages_24v << "\n"
|
||||
" For 48 V unit: " << p18::bat_ac_recharge_voltages_48v << "\n"
|
||||
"\n"
|
||||
" dv: re-discharging voltage\n"
|
||||
" For 12 V unit: " << p18::bat_ac_redischarging_voltages_12v << "\n"
|
||||
" For 24 V unit: " << p18::bat_ac_redischarging_voltages_24v << "\n"
|
||||
" For 48 V unit: " << p18::bat_ac_redischarging_voltages_48v << "\n"
|
||||
" dv: re-discharge voltage\n"
|
||||
" For 12 V unit: " << p18::bat_ac_redischarge_voltages_12v << "\n"
|
||||
" For 24 V unit: " << p18::bat_ac_redischarge_voltages_24v << "\n"
|
||||
" For 48 V unit: " << p18::bat_ac_redischarge_voltages_48v << "\n"
|
||||
"\n"
|
||||
" set-charging-source-priority <id> <priority>\n"
|
||||
" id: Parallel machine ID (use 0 for a single model)\n"
|
||||
" set-charge-source-priority <id> <priority>\n"
|
||||
" id: Parallel machine ID\n"
|
||||
" priority: SF|SU|S\n"
|
||||
" 'SF' means " << p18::ChargerSourcePriority::SolarFirst << ",\n"
|
||||
" 'SU' means " << p18::ChargerSourcePriority::SolarAndUtility << "\n"
|
||||
" 'S' means " << p18::ChargerSourcePriority::SolarOnly << "\n"
|
||||
" 'SF' means " << p18::ChargeSourcePriority::SolarFirst << "\n"
|
||||
" 'SU' means " << p18::ChargeSourcePriority::SolarAndUtility << "\n"
|
||||
" 'S' means " << p18::ChargeSourcePriority::SolarOnly << "\n"
|
||||
"\n"
|
||||
" set-solar-power-priority BLU|LBU\n"
|
||||
" 'BLU' means " << p18::SolarPowerPriority::BatteryLoadUtility << "\n"
|
||||
@ -165,16 +168,16 @@ static void usage(const char* progname) {
|
||||
"\n"
|
||||
" set-ac-input-voltage-range APPLIANCE|UPS\n"
|
||||
" set-battery-type AGM|FLOODED|USER\n"
|
||||
" set-output-model <id> <model>\n"
|
||||
" id: Parallel machine ID (use 0 for a single model)\n"
|
||||
" model: SM|P|P1|P2|P3\n"
|
||||
" SM: " << p18::OutputModelSetting::SingleModule << "\n"
|
||||
" P: " << p18::OutputModelSetting::ParallelOutput << "\n"
|
||||
" P1: " << p18::OutputModelSetting::Phase1OfThreePhaseOutput << "\n"
|
||||
" P2: " << p18::OutputModelSetting::Phase2OfThreePhaseOutput << "\n"
|
||||
" P3: " << p18::OutputModelSetting::Phase3OfThreePhaseOutput << "\n"
|
||||
" set-output-mode <id> <mode>\n"
|
||||
" id: Machine ID\n"
|
||||
" mode: S|P|1|2|3\n"
|
||||
" S: " << p18::OutputMode::SingleOutput << "\n"
|
||||
" P: " << p18::OutputMode::ParallelOutput << "\n"
|
||||
" 1: " << p18::OutputMode::Phase_1_of_3 << "\n"
|
||||
" 2: " << p18::OutputMode::Phase_2_of_3 << "\n"
|
||||
" 3: " << p18::OutputMode::Phase_3_of_3 << "\n"
|
||||
"\n"
|
||||
" set-battery-cut-off-voltage <v>\n"
|
||||
" set-battery-cutoff-voltage <v>\n"
|
||||
" v: Cut-off voltage (40.0~48.0)\n"
|
||||
"\n"
|
||||
" set-solar-configuration <id>\n"
|
||||
@ -191,14 +194,16 @@ static void usage(const char* progname) {
|
||||
" mm: Minutes\n"
|
||||
" ss: Seconds\n"
|
||||
"\n"
|
||||
" set-ac-charging-time <start> <end>\n"
|
||||
" set-ac-charge-time <start> <end>\n"
|
||||
" start: Starting time, hh:mm format\n"
|
||||
" end: Ending time, hh:mm format\n"
|
||||
"\n"
|
||||
" set-ac-loads-supply-time <start> <end>\n"
|
||||
" set-ac-supply-time <start> <end>\n"
|
||||
" start: Starting time, hh:mm format\n"
|
||||
" end: Ending time, hh:mm format\n"
|
||||
"\n"
|
||||
"Note: use 0 as parallel machine ID for single machine.\n"
|
||||
"\n"
|
||||
"Flags:\n";
|
||||
for (const p18::Flag& flag: p18::flags)
|
||||
std::cout << " " << flag.flag << ": " << flag.description << "\n";
|
||||
@ -260,6 +265,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
u16 usbVendorId = voltronic::USBDevice::VENDOR_ID;
|
||||
u16 usbDeviceId = voltronic::USBDevice::PRODUCT_ID;
|
||||
std::string usbDevicePath {};
|
||||
|
||||
std::string serialDeviceName(voltronic::SerialDevice::DEVICE_NAME);
|
||||
voltronic::SerialBaudRate serialBaudRate = voltronic::SerialDevice::BAUD_RATE;
|
||||
@ -278,6 +284,7 @@ int main(int argc, char *argv[]) {
|
||||
{"device", required_argument, nullptr, LO_DEVICE},
|
||||
{"usb-vendor-id", required_argument, nullptr, LO_USB_VENDOR_ID},
|
||||
{"usb-device-id", required_argument, nullptr, LO_USB_DEVICE_ID},
|
||||
{"usb-path", required_argument, nullptr, LO_USB_PATH},
|
||||
{"serial-name", required_argument, nullptr, LO_SERIAL_NAME},
|
||||
{"serial-baud-rate", required_argument, nullptr, LO_SERIAL_BAUD_RATE},
|
||||
{"serial-data-bits", required_argument, nullptr, LO_SERIAL_DATA_BITS},
|
||||
@ -355,6 +362,10 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
break;
|
||||
|
||||
case LO_USB_PATH:
|
||||
usbDevicePath = arg;
|
||||
break;
|
||||
|
||||
case LO_SERIAL_NAME:
|
||||
serialDeviceName = arg;
|
||||
break;
|
||||
@ -440,8 +451,12 @@ int main(int argc, char *argv[]) {
|
||||
std::shared_ptr<voltronic::Device> dev;
|
||||
switch (deviceType) {
|
||||
case DeviceType::USB:
|
||||
if (usbDevicePath.empty()) {
|
||||
dev = std::shared_ptr<voltronic::Device>(new voltronic::USBDevice(usbVendorId,
|
||||
usbDeviceId));
|
||||
} else {
|
||||
dev = std::shared_ptr<voltronic::Device>(new voltronic::USBDevice(usbDevicePath));
|
||||
}
|
||||
break;
|
||||
|
||||
case DeviceType::Pseudo:
|
||||
|
@ -42,7 +42,10 @@ static void usage(const char* progname) {
|
||||
std::cout << std::hex << std::setfill('0') <<
|
||||
"USB device options:\n"
|
||||
" --usb-vendor-id <ID>: Vendor ID (default: " << std::setw(4) << voltronic::USBDevice::VENDOR_ID << ")\n"
|
||||
" --usb-device-id <ID>: Device ID (default: " << std::setw(4) << voltronic::USBDevice::PRODUCT_ID << ")\n";
|
||||
" --usb-device-id <ID>: Device ID (default: " << std::setw(4) << voltronic::USBDevice::PRODUCT_ID << ")\n"
|
||||
"\n"
|
||||
" Alternatively, you can specify device path (e.g., /dev/hidraw0):\n"
|
||||
" --usb-path <PATH>: Device path\n";
|
||||
std::cout.flags(f);
|
||||
|
||||
std::cout << "\n"
|
||||
@ -73,6 +76,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
unsigned short usbVendorId = voltronic::USBDevice::VENDOR_ID;
|
||||
unsigned short usbDeviceId = voltronic::USBDevice::PRODUCT_ID;
|
||||
std::string usbDevicePath {};
|
||||
|
||||
std::string serialDeviceName(voltronic::SerialDevice::DEVICE_NAME);
|
||||
voltronic::SerialBaudRate serialBaudRate = voltronic::SerialDevice::BAUD_RATE;
|
||||
@ -92,6 +96,7 @@ int main(int argc, char *argv[]) {
|
||||
{"device-error-limit", required_argument, nullptr, LO_DEVICE_ERROR_LIMIT},
|
||||
{"usb-vendor-id", required_argument, nullptr, LO_USB_VENDOR_ID},
|
||||
{"usb-device-id", required_argument, nullptr, LO_USB_DEVICE_ID},
|
||||
{"usb-path", required_argument, nullptr, LO_USB_PATH},
|
||||
{"serial-name", required_argument, nullptr, LO_SERIAL_NAME},
|
||||
{"serial-baud-rate", required_argument, nullptr, LO_SERIAL_BAUD_RATE},
|
||||
{"serial-data-bits", required_argument, nullptr, LO_SERIAL_DATA_BITS},
|
||||
@ -176,6 +181,10 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
break;
|
||||
|
||||
case LO_USB_PATH:
|
||||
usbDevicePath = arg;
|
||||
break;
|
||||
|
||||
case LO_SERIAL_NAME:
|
||||
serialDeviceName = arg;
|
||||
break;
|
||||
@ -243,7 +252,12 @@ int main(int argc, char *argv[]) {
|
||||
try {
|
||||
switch (deviceType) {
|
||||
case DeviceType::USB:
|
||||
dev = std::shared_ptr<voltronic::Device>(new voltronic::USBDevice(usbVendorId, usbDeviceId));
|
||||
if (usbDevicePath.empty()) {
|
||||
dev = std::shared_ptr<voltronic::Device>(new voltronic::USBDevice(usbVendorId,
|
||||
usbDeviceId));
|
||||
} else {
|
||||
dev = std::shared_ptr<voltronic::Device>(new voltronic::USBDevice(usbDevicePath));
|
||||
}
|
||||
break;
|
||||
|
||||
case DeviceType::Pseudo:
|
||||
|
@ -3,6 +3,8 @@
|
||||
#ifndef INVERTER_TOOLS_NUMERIC_TYPES_H
|
||||
#define INVERTER_TOOLS_NUMERIC_TYPES_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
|
@ -65,42 +65,42 @@ std::shared_ptr<response_type::BaseResponse> Client::execute(p18::CommandType co
|
||||
RESPONSE_CASE(YearGenerated)
|
||||
RESPONSE_CASE(MonthGenerated)
|
||||
RESPONSE_CASE(DayGenerated)
|
||||
RESPONSE_CASE(SeriesNumber)
|
||||
RESPONSE_CASE(SerialNumber)
|
||||
RESPONSE_CASE(CPUVersion)
|
||||
RESPONSE_CASE(RatedInformation)
|
||||
RESPONSE_CASE(GeneralStatus)
|
||||
RESPONSE_CASE(WorkingMode)
|
||||
RESPONSE_CASE(FaultsAndWarnings)
|
||||
RESPONSE_CASE(FlagsAndStatuses)
|
||||
RESPONSE_CASE(Defaults)
|
||||
RESPONSE_CASE(AllowedChargingCurrents)
|
||||
RESPONSE_CASE(AllowedACChargingCurrents)
|
||||
RESPONSE_CASE(RatedDefaults)
|
||||
RESPONSE_CASE(AllowedChargeCurrents)
|
||||
RESPONSE_CASE(AllowedACChargeCurrents)
|
||||
RESPONSE_CASE(ParallelRatedInformation)
|
||||
RESPONSE_CASE(ParallelGeneralStatus)
|
||||
RESPONSE_CASE(ACChargingTimeBucket)
|
||||
RESPONSE_CASE(ACLoadsSupplyTimeBucket)
|
||||
RESPONSE_CASE(ACChargeTimeBucket)
|
||||
RESPONSE_CASE(ACSupplyTimeBucket)
|
||||
|
||||
case CommandType::SetLoads:
|
||||
case CommandType::SetACSupply:
|
||||
case CommandType::SetFlag:
|
||||
case CommandType::SetDefaults:
|
||||
case CommandType::SetBatteryMaxChargingCurrent:
|
||||
case CommandType::SetBatteryMaxACChargingCurrent:
|
||||
case CommandType::SetBatteryMaxChargeCurrent:
|
||||
case CommandType::SetBatteryMaxACChargeCurrent:
|
||||
case CommandType::SetACOutputFreq:
|
||||
case CommandType::SetBatteryMaxChargingVoltage:
|
||||
case CommandType::SetACOutputRatedVoltage:
|
||||
case CommandType::SetBatteryMaxChargeVoltage:
|
||||
case CommandType::SetACOutputVoltage:
|
||||
case CommandType::SetOutputSourcePriority:
|
||||
case CommandType::SetBatteryChargingThresholds:
|
||||
case CommandType::SetChargingSourcePriority:
|
||||
case CommandType::SetBatteryChargeThresholds:
|
||||
case CommandType::SetChargeSourcePriority:
|
||||
case CommandType::SetSolarPowerPriority:
|
||||
case CommandType::SetACInputVoltageRange:
|
||||
case CommandType::SetBatteryType:
|
||||
case CommandType::SetOutputModel:
|
||||
case CommandType::SetOutputMode:
|
||||
case CommandType::SetBatteryCutOffVoltage:
|
||||
case CommandType::SetSolarConfig:
|
||||
case CommandType::ClearGenerated:
|
||||
case CommandType::SetDateTime:
|
||||
case CommandType::SetACChargingTimeBucket:
|
||||
case CommandType::SetACLoadsSupplyTimeBucket:
|
||||
case CommandType::SetACChargeTimeBucket:
|
||||
case CommandType::SetACSupplyTimeBucket:
|
||||
response = MKRESPONSE(SetResponse);
|
||||
break;
|
||||
}
|
||||
@ -132,7 +132,7 @@ std::string Client::packArguments(p18::CommandType commandType, std::vector<std:
|
||||
case CommandType::SetSolarPowerPriority:
|
||||
case CommandType::SetACInputVoltageRange:
|
||||
case CommandType::SetBatteryType:
|
||||
case CommandType::SetLoads:
|
||||
case CommandType::SetACSupply:
|
||||
buf << arguments[0];
|
||||
break;
|
||||
|
||||
@ -153,8 +153,8 @@ std::string Client::packArguments(p18::CommandType commandType, std::vector<std:
|
||||
buf << arguments[0];
|
||||
break;
|
||||
|
||||
case CommandType::SetBatteryMaxChargingCurrent:
|
||||
case CommandType::SetBatteryMaxACChargingCurrent:
|
||||
case CommandType::SetBatteryMaxChargeCurrent:
|
||||
case CommandType::SetBatteryMaxACChargeCurrent:
|
||||
buf << arguments[0] << ",";
|
||||
buf << std::setw(3) << std::stoi(arguments[1]);
|
||||
break;
|
||||
@ -163,8 +163,8 @@ std::string Client::packArguments(p18::CommandType commandType, std::vector<std:
|
||||
buf << std::setw(2) << std::stoi(arguments[0]);
|
||||
break;
|
||||
|
||||
case CommandType::SetBatteryMaxChargingVoltage:
|
||||
case CommandType::SetBatteryChargingThresholds: {
|
||||
case CommandType::SetBatteryMaxChargeVoltage:
|
||||
case CommandType::SetBatteryChargeThresholds: {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
double val = std::stod(arguments[i]);
|
||||
buf << std::setw(3) << (int)round(val*10);
|
||||
@ -174,13 +174,13 @@ std::string Client::packArguments(p18::CommandType commandType, std::vector<std:
|
||||
break;
|
||||
}
|
||||
|
||||
case CommandType::SetACOutputRatedVoltage: {
|
||||
case CommandType::SetACOutputVoltage: {
|
||||
buf << std::setw(4) << (std::stoi(arguments[0])*10);
|
||||
break;
|
||||
}
|
||||
|
||||
case CommandType::SetChargingSourcePriority:
|
||||
case CommandType::SetOutputModel:
|
||||
case CommandType::SetChargeSourcePriority:
|
||||
case CommandType::SetOutputMode:
|
||||
buf << arguments[0] << "," << arguments[1];
|
||||
break;
|
||||
|
||||
@ -210,8 +210,8 @@ std::string Client::packArguments(p18::CommandType commandType, std::vector<std:
|
||||
break;
|
||||
}
|
||||
|
||||
case CommandType::SetACChargingTimeBucket:
|
||||
case CommandType::SetACLoadsSupplyTimeBucket:
|
||||
case CommandType::SetACChargeTimeBucket:
|
||||
case CommandType::SetACSupplyTimeBucket:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
buf << std::setw(2) << std::stoi(arguments[i]);
|
||||
if (i == 1)
|
||||
|
@ -24,41 +24,41 @@ const std::map<std::string, p18::CommandType> client_commands = {
|
||||
{"get-year-generated", p18::CommandType::GetYearGenerated},
|
||||
{"get-month-generated", p18::CommandType::GetMonthGenerated},
|
||||
{"get-day-generated", p18::CommandType::GetDayGenerated},
|
||||
{"get-series-number", p18::CommandType::GetSeriesNumber},
|
||||
{"get-serial-number", p18::CommandType::GetSerialNumber},
|
||||
{"get-cpu-version", p18::CommandType::GetCPUVersion},
|
||||
{"get-rated", p18::CommandType::GetRatedInformation},
|
||||
{"get-status", p18::CommandType::GetGeneralStatus},
|
||||
{"get-mode", p18::CommandType::GetWorkingMode},
|
||||
{"get-errors", p18::CommandType::GetFaultsAndWarnings},
|
||||
{"get-flags", p18::CommandType::GetFlagsAndStatuses},
|
||||
{"get-rated-defaults", p18::CommandType::GetDefaults},
|
||||
{"get-allowed-charging-currents", p18::CommandType::GetAllowedChargingCurrents},
|
||||
{"get-allowed-ac-charging-currents", p18::CommandType::GetAllowedACChargingCurrents},
|
||||
{"get-rated-defaults", p18::CommandType::GetRatedDefaults},
|
||||
{"get-allowed-charge-currents", p18::CommandType::GetAllowedChargeCurrents},
|
||||
{"get-allowed-ac-charge-currents", p18::CommandType::GetAllowedACChargeCurrents},
|
||||
{"get-p-rated", p18::CommandType::GetParallelRatedInformation},
|
||||
{"get-p-status", p18::CommandType::GetParallelGeneralStatus},
|
||||
{"get-ac-charging-time", p18::CommandType::GetACChargingTimeBucket},
|
||||
{"get-ac-loads-supply-time", p18::CommandType::GetACLoadsSupplyTimeBucket},
|
||||
{"set-loads-supply", p18::CommandType::SetLoads},
|
||||
{"get-ac-charge-time", p18::CommandType::GetACChargeTimeBucket},
|
||||
{"get-ac-supply-time", p18::CommandType::GetACSupplyTimeBucket},
|
||||
{"set-ac-supply", p18::CommandType::SetACSupply},
|
||||
{"set-flag", p18::CommandType::SetFlag},
|
||||
{"set-rated-defaults", p18::CommandType::SetDefaults},
|
||||
{"set-max-charging-current", p18::CommandType::SetBatteryMaxChargingCurrent},
|
||||
{"set-max-ac-charging-current", p18::CommandType::SetBatteryMaxACChargingCurrent},
|
||||
{"set-max-charge-current", p18::CommandType::SetBatteryMaxChargeCurrent},
|
||||
{"set-max-ac-charge-current", p18::CommandType::SetBatteryMaxACChargeCurrent},
|
||||
{"set-ac-output-freq", p18::CommandType::SetACOutputFreq},
|
||||
{"set-max-charging-voltage", p18::CommandType::SetBatteryMaxChargingVoltage},
|
||||
{"set-ac-output-voltage", p18::CommandType::SetACOutputRatedVoltage},
|
||||
{"set-max-charge-voltage", p18::CommandType::SetBatteryMaxChargeVoltage},
|
||||
{"set-ac-output-voltage", p18::CommandType::SetACOutputVoltage},
|
||||
{"set-output-source-priority", p18::CommandType::SetOutputSourcePriority},
|
||||
{"set-charging-thresholds", p18::CommandType::SetBatteryChargingThresholds}, /* Battery re-charging and re-discharging voltage when utility is available */
|
||||
{"set-charging-source-priority", p18::CommandType::SetChargingSourcePriority},
|
||||
{"set-charge-thresholds", p18::CommandType::SetBatteryChargeThresholds}, /* Battery re-charge and re-discharge voltage when utility is available */
|
||||
{"set-charge-source-priority", p18::CommandType::SetChargeSourcePriority},
|
||||
{"set-solar-power-priority", p18::CommandType::SetSolarPowerPriority},
|
||||
{"set-ac-input-voltage-range", p18::CommandType::SetACInputVoltageRange},
|
||||
{"set-battery-type", p18::CommandType::SetBatteryType},
|
||||
{"set-output-model", p18::CommandType::SetOutputModel},
|
||||
{"set-battery-cut-off-voltage", p18::CommandType::SetBatteryCutOffVoltage},
|
||||
{"set-output-mode", p18::CommandType::SetOutputMode},
|
||||
{"set-battery-cutoff-voltage", p18::CommandType::SetBatteryCutOffVoltage},
|
||||
{"set-solar-configuration", p18::CommandType::SetSolarConfig},
|
||||
{"clear-generated-data", p18::CommandType::ClearGenerated},
|
||||
{"set-date-time", p18::CommandType::SetDateTime},
|
||||
{"set-ac-charging-time", p18::CommandType::SetACChargingTimeBucket},
|
||||
{"set-ac-loads-supply-time", p18::CommandType::SetACLoadsSupplyTimeBucket},
|
||||
{"set-ac-charge-time", p18::CommandType::SetACChargeTimeBucket},
|
||||
{"set-ac-supply-time", p18::CommandType::SetACSupplyTimeBucket},
|
||||
};
|
||||
|
||||
static void validate_date_args(const std::string* ys, const std::string* ms, const std::string* ds) {
|
||||
@ -200,7 +200,7 @@ p18::CommandType validate_input(std::string& command,
|
||||
throw std::invalid_argument("invalid argument");
|
||||
break;
|
||||
|
||||
case p18::CommandType::SetLoads: {
|
||||
case p18::CommandType::SetACSupply: {
|
||||
GET_ARGS(1);
|
||||
std::string &arg = arguments[0];
|
||||
if (arg != "0" && arg != "1")
|
||||
@ -229,8 +229,8 @@ p18::CommandType validate_input(std::string& command,
|
||||
break;
|
||||
}
|
||||
|
||||
case p18::CommandType::SetBatteryMaxChargingCurrent:
|
||||
case p18::CommandType::SetBatteryMaxACChargingCurrent: {
|
||||
case p18::CommandType::SetBatteryMaxChargeCurrent:
|
||||
case p18::CommandType::SetBatteryMaxACChargeCurrent: {
|
||||
GET_ARGS(2);
|
||||
|
||||
auto id = static_cast<unsigned>(std::stoul(arguments[0]));
|
||||
@ -254,7 +254,7 @@ p18::CommandType validate_input(std::string& command,
|
||||
break;
|
||||
}
|
||||
|
||||
case p18::CommandType::SetBatteryMaxChargingVoltage: {
|
||||
case p18::CommandType::SetBatteryMaxChargeVoltage: {
|
||||
GET_ARGS(2);
|
||||
|
||||
float cv = std::stof(arguments[0]);
|
||||
@ -269,13 +269,13 @@ p18::CommandType validate_input(std::string& command,
|
||||
break;
|
||||
}
|
||||
|
||||
case p18::CommandType::SetACOutputRatedVoltage: {
|
||||
case p18::CommandType::SetACOutputVoltage: {
|
||||
GET_ARGS(1);
|
||||
|
||||
auto v = static_cast<unsigned>(std::stoul(arguments[0]));
|
||||
|
||||
bool matchFound = false;
|
||||
for (const auto &item: p18::ac_output_rated_voltages) {
|
||||
for (const auto &item: p18::ac_output_voltages) {
|
||||
if (v == item) {
|
||||
matchFound = true;
|
||||
break;
|
||||
@ -301,26 +301,26 @@ p18::CommandType validate_input(std::string& command,
|
||||
break;
|
||||
}
|
||||
|
||||
case p18::CommandType::SetBatteryChargingThresholds: {
|
||||
case p18::CommandType::SetBatteryChargeThresholds: {
|
||||
GET_ARGS(2);
|
||||
|
||||
float cv = std::stof(arguments[0]);
|
||||
float dv = std::stof(arguments[1]);
|
||||
|
||||
if (index_of(p18::bat_ac_recharging_voltages_12v, cv) == -1 &&
|
||||
index_of(p18::bat_ac_recharging_voltages_24v, cv) == -1 &&
|
||||
index_of(p18::bat_ac_recharging_voltages_48v, cv) == -1)
|
||||
if (index_of(p18::bat_ac_recharge_voltages_12v, cv) == -1 &&
|
||||
index_of(p18::bat_ac_recharge_voltages_24v, cv) == -1 &&
|
||||
index_of(p18::bat_ac_recharge_voltages_48v, cv) == -1)
|
||||
throw std::invalid_argument("invalid CV");
|
||||
|
||||
if (index_of(p18::bat_ac_redischarging_voltages_12v, dv) == -1 &&
|
||||
index_of(p18::bat_ac_redischarging_voltages_24v, dv) == -1 &&
|
||||
index_of(p18::bat_ac_redischarging_voltages_48v, dv) == -1)
|
||||
if (index_of(p18::bat_ac_redischarge_voltages_12v, dv) == -1 &&
|
||||
index_of(p18::bat_ac_redischarge_voltages_24v, dv) == -1 &&
|
||||
index_of(p18::bat_ac_redischarge_voltages_48v, dv) == -1)
|
||||
throw std::invalid_argument("invalid DV");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case p18::CommandType::SetChargingSourcePriority: {
|
||||
case p18::CommandType::SetChargeSourcePriority: {
|
||||
GET_ARGS(2);
|
||||
|
||||
auto id = static_cast<unsigned>(std::stoul(arguments[0]));
|
||||
@ -370,14 +370,14 @@ p18::CommandType validate_input(std::string& command,
|
||||
break;
|
||||
}
|
||||
|
||||
case p18::CommandType::SetOutputModel: {
|
||||
case p18::CommandType::SetOutputMode: {
|
||||
GET_ARGS(2);
|
||||
|
||||
auto id = static_cast<unsigned>(std::stoul(arguments[0]));
|
||||
if (!p18::is_valid_parallel_id(id))
|
||||
throw std::invalid_argument("invalid id");
|
||||
|
||||
std::array<std::string, 5> allowed({"SM", "P", "P1", "P2", "P3"});
|
||||
std::array<std::string, 5> allowed({"S", "P", "1", "2", "3"});
|
||||
long index = index_of(allowed, arguments[1]);
|
||||
if (index == -1)
|
||||
throw std::invalid_argument("invalid model");
|
||||
@ -414,8 +414,8 @@ p18::CommandType validate_input(std::string& command,
|
||||
break;
|
||||
}
|
||||
|
||||
case p18::CommandType::SetACChargingTimeBucket:
|
||||
case p18::CommandType::SetACLoadsSupplyTimeBucket: {
|
||||
case p18::CommandType::SetACChargeTimeBucket:
|
||||
case p18::CommandType::SetACSupplyTimeBucket: {
|
||||
GET_ARGS(2);
|
||||
|
||||
std::vector<std::string> start = split(arguments[0], ':');
|
||||
|
@ -14,54 +14,54 @@ const std::map<CommandType, std::string> raw_commands = {
|
||||
{CommandType::GetYearGenerated, "EY"},
|
||||
{CommandType::GetMonthGenerated, "EM"},
|
||||
{CommandType::GetDayGenerated, "ED"},
|
||||
{CommandType::GetSeriesNumber, "ID"},
|
||||
{CommandType::GetSerialNumber, "ID"},
|
||||
{CommandType::GetCPUVersion, "VFW"},
|
||||
{CommandType::GetRatedInformation, "PIRI"},
|
||||
{CommandType::GetGeneralStatus, "GS"},
|
||||
{CommandType::GetWorkingMode, "MOD"},
|
||||
{CommandType::GetFaultsAndWarnings, "FWS"},
|
||||
{CommandType::GetFlagsAndStatuses, "FLAG"},
|
||||
{CommandType::GetDefaults, "DI"},
|
||||
{CommandType::GetAllowedChargingCurrents, "MCHGCR"},
|
||||
{CommandType::GetAllowedACChargingCurrents, "MUCHGCR"},
|
||||
{CommandType::GetRatedDefaults, "DI"},
|
||||
{CommandType::GetAllowedChargeCurrents, "MCHGCR"},
|
||||
{CommandType::GetAllowedACChargeCurrents, "MUCHGCR"},
|
||||
{CommandType::GetParallelRatedInformation, "PRI"},
|
||||
{CommandType::GetParallelGeneralStatus, "PGS"},
|
||||
{CommandType::GetACChargingTimeBucket, "ACCT"},
|
||||
{CommandType::GetACLoadsSupplyTimeBucket, "ACLT"},
|
||||
{CommandType::SetLoads, "LON"},
|
||||
{CommandType::GetACChargeTimeBucket, "ACCT"},
|
||||
{CommandType::GetACSupplyTimeBucket, "ACLT"},
|
||||
{CommandType::SetACSupply, "LON"},
|
||||
{CommandType::SetFlag, "P"},
|
||||
{CommandType::SetDefaults, "PF"},
|
||||
{CommandType::SetBatteryMaxChargingCurrent, "MCHGC"},
|
||||
{CommandType::SetBatteryMaxACChargingCurrent, "MUCHGC"},
|
||||
{CommandType::SetBatteryMaxChargeCurrent, "MCHGC"},
|
||||
{CommandType::SetBatteryMaxACChargeCurrent, "MUCHGC"},
|
||||
/* The protocol documentation defines two commands, "F50" and "F60",
|
||||
but it's identical as if there were just one "F" command with an argument. */
|
||||
{CommandType::SetACOutputFreq, "F"},
|
||||
{CommandType::SetBatteryMaxChargingVoltage, "MCHGV"},
|
||||
{CommandType::SetACOutputRatedVoltage, "V"},
|
||||
{CommandType::SetBatteryMaxChargeVoltage, "MCHGV"},
|
||||
{CommandType::SetACOutputVoltage, "V"},
|
||||
{CommandType::SetOutputSourcePriority, "POP"},
|
||||
{CommandType::SetBatteryChargingThresholds, "BUCD"},
|
||||
{CommandType::SetChargingSourcePriority, "PCP"},
|
||||
{CommandType::SetBatteryChargeThresholds, "BUCD"},
|
||||
{CommandType::SetChargeSourcePriority, "PCP"},
|
||||
{CommandType::SetSolarPowerPriority, "PSP"},
|
||||
{CommandType::SetACInputVoltageRange, "PGR"},
|
||||
{CommandType::SetBatteryType, "PBT"},
|
||||
{CommandType::SetOutputModel, "POPM"},
|
||||
{CommandType::SetOutputMode, "POPM"},
|
||||
{CommandType::SetBatteryCutOffVoltage, "PSDV"},
|
||||
{CommandType::SetSolarConfig, "ID"},
|
||||
{CommandType::ClearGenerated, "CLE"},
|
||||
{CommandType::SetDateTime, "DAT"},
|
||||
{CommandType::SetACChargingTimeBucket, "ACCT"},
|
||||
{CommandType::SetACLoadsSupplyTimeBucket, "ACLT"},
|
||||
{CommandType::SetACChargeTimeBucket, "ACCT"},
|
||||
{CommandType::SetACSupplyTimeBucket, "ACLT"},
|
||||
};
|
||||
|
||||
const std::array<int, 5> ac_output_rated_voltages = {202, 208, 220, 230, 240};
|
||||
const std::array<int, 5> ac_output_voltages = {202, 208, 220, 230, 240};
|
||||
|
||||
const std::array<float, 8> bat_ac_recharging_voltages_12v = {11, 11.3, 11.5, 11.8, 12, 12.3, 12.5, 12.8};
|
||||
const std::array<float, 8> bat_ac_recharging_voltages_24v = {22, 22.5, 23, 23.5, 24, 24.5, 25, 25.5};
|
||||
const std::array<float, 8> bat_ac_recharging_voltages_48v = {44, 45, 46, 47, 48, 49, 50, 51};
|
||||
const std::array<float, 8> bat_ac_recharge_voltages_12v = {11, 11.3, 11.5, 11.8, 12, 12.3, 12.5, 12.8};
|
||||
const std::array<float, 8> bat_ac_recharge_voltages_24v = {22, 22.5, 23, 23.5, 24, 24.5, 25, 25.5};
|
||||
const std::array<float, 8> bat_ac_recharge_voltages_48v = {44, 45, 46, 47, 48, 49, 50, 51};
|
||||
|
||||
const std::array<float, 12> bat_ac_redischarging_voltages_12v = {0, 12, 12.3, 12.5, 12.8, 13, 13.3, 13.5, 13.8, 14, 14.3, 14.5};
|
||||
const std::array<float, 12> bat_ac_redischarging_voltages_24v = {0, 24, 24.5, 25, 25.5, 26, 26.5, 27, 27.5, 28, 28.5, 29};
|
||||
const std::array<float, 12> bat_ac_redischarging_voltages_48v = {0, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58};
|
||||
const std::array<float, 12> bat_ac_redischarge_voltages_12v = {0, 12, 12.3, 12.5, 12.8, 13, 13.3, 13.5, 13.8, 14, 14.3, 14.5};
|
||||
const std::array<float, 12> bat_ac_redischarge_voltages_24v = {0, 24, 24.5, 25, 25.5, 26, 26.5, 27, 27.5, 28, 28.5, 29};
|
||||
const std::array<float, 12> bat_ac_redischarge_voltages_48v = {0, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58};
|
||||
|
||||
const std::map<int, std::string> fault_codes = {
|
||||
{1, "Fan is locked"},
|
||||
@ -133,13 +133,13 @@ ENUM_STR(OutputSourcePriority) {
|
||||
ENUM_STR_DEFAULT;
|
||||
}
|
||||
|
||||
ENUM_STR(ChargerSourcePriority) {
|
||||
ENUM_STR(ChargeSourcePriority) {
|
||||
switch (val) {
|
||||
case ChargerSourcePriority::SolarFirst:
|
||||
case ChargeSourcePriority::SolarFirst:
|
||||
return os << "Solar-First";
|
||||
case ChargerSourcePriority::SolarAndUtility:
|
||||
case ChargeSourcePriority::SolarAndUtility:
|
||||
return os << "Solar-and-Utility";
|
||||
case ChargerSourcePriority::SolarOnly:
|
||||
case ChargeSourcePriority::SolarOnly:
|
||||
return os << "Solar-only";
|
||||
}
|
||||
ENUM_STR_DEFAULT;
|
||||
@ -161,18 +161,18 @@ ENUM_STR(Topology) {
|
||||
ENUM_STR_DEFAULT;
|
||||
}
|
||||
|
||||
ENUM_STR(OutputModelSetting) {
|
||||
ENUM_STR(OutputMode) {
|
||||
switch (val) {
|
||||
case OutputModelSetting::SingleModule:
|
||||
return os << "Single module";
|
||||
case OutputModelSetting::ParallelOutput:
|
||||
case OutputMode::SingleOutput:
|
||||
return os << "Single output";
|
||||
case OutputMode::ParallelOutput:
|
||||
return os << "Parallel output";
|
||||
case OutputModelSetting::Phase1OfThreePhaseOutput:
|
||||
return os << "Phase 1 of three phase output";
|
||||
case OutputModelSetting::Phase2OfThreePhaseOutput:
|
||||
return os << "Phase 2 of three phase output";
|
||||
case OutputModelSetting::Phase3OfThreePhaseOutput:
|
||||
return os << "Phase 3 of three phase";
|
||||
case OutputMode::Phase_1_of_3:
|
||||
return os << "Phase 1 of 3-phase output";
|
||||
case OutputMode::Phase_2_of_3:
|
||||
return os << "Phase 2 of 3-phase output";
|
||||
case OutputMode::Phase_3_of_3:
|
||||
return os << "Phase 3 of 3-phase";
|
||||
}
|
||||
ENUM_STR_DEFAULT;
|
||||
}
|
||||
|
@ -13,15 +13,15 @@ namespace p18 {
|
||||
|
||||
extern const std::map<CommandType, std::string> raw_commands;
|
||||
|
||||
extern const std::array<int, 5> ac_output_rated_voltages;
|
||||
extern const std::array<int, 5> ac_output_voltages;
|
||||
|
||||
extern const std::array<float, 8> bat_ac_recharging_voltages_12v;
|
||||
extern const std::array<float, 8> bat_ac_recharging_voltages_24v;
|
||||
extern const std::array<float, 8> bat_ac_recharging_voltages_48v;
|
||||
extern const std::array<float, 8> bat_ac_recharge_voltages_12v;
|
||||
extern const std::array<float, 8> bat_ac_recharge_voltages_24v;
|
||||
extern const std::array<float, 8> bat_ac_recharge_voltages_48v;
|
||||
|
||||
extern const std::array<float, 12> bat_ac_redischarging_voltages_12v;
|
||||
extern const std::array<float, 12> bat_ac_redischarging_voltages_24v;
|
||||
extern const std::array<float, 12> bat_ac_redischarging_voltages_48v;
|
||||
extern const std::array<float, 12> bat_ac_redischarge_voltages_12v;
|
||||
extern const std::array<float, 12> bat_ac_redischarge_voltages_24v;
|
||||
extern const std::array<float, 12> bat_ac_redischarge_voltages_48v;
|
||||
|
||||
extern const std::map<int, std::string> fault_codes;
|
||||
|
||||
|
@ -27,6 +27,19 @@ typedef formatter::TableItem<VariantHolder> LINE;
|
||||
|
||||
using formatter::Unit;
|
||||
|
||||
|
||||
/**
|
||||
* Helpers
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& os, FieldLength fl) {
|
||||
if (fl.min_ == fl.max_)
|
||||
os << fl.min_;
|
||||
else
|
||||
os << "[" << fl.min_ << ", " << fl.max_ << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base responses
|
||||
*/
|
||||
@ -58,23 +71,32 @@ size_t GetResponse::getDataSize() const {
|
||||
return rawSize_ - 5;
|
||||
}
|
||||
|
||||
std::vector<std::string> GetResponse::getList(std::vector<size_t> itemLengths) const {
|
||||
std::vector<std::string> GetResponse::getList(std::vector<FieldLength> itemLengths, int expectAtLeast) const {
|
||||
std::string buf(getData(), getDataSize());
|
||||
auto list = ::split(buf, ',');
|
||||
|
||||
if (expectAtLeast == -1)
|
||||
expectAtLeast = (int)itemLengths.size();
|
||||
|
||||
if (!itemLengths.empty()) {
|
||||
// check list length
|
||||
if (list.size() < itemLengths.size()) {
|
||||
if (list.size() < expectAtLeast) {
|
||||
std::ostringstream error;
|
||||
error << "while parsing " << demangle_type_name(typeid(*this).name());
|
||||
error << ": list is expected to be " << itemLengths.size() << " items long, ";
|
||||
error << ": list is expected to be " << expectAtLeast << " items long, ";
|
||||
error << "got only " << list.size() << " items";
|
||||
throw ParseError(error.str());
|
||||
}
|
||||
|
||||
// check each item's length
|
||||
for (int i = 0; i < itemLengths.size(); i++) {
|
||||
if (list[i].size() != itemLengths[i]) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (i >= itemLengths.size()) {
|
||||
myerr << "while parsing " << demangle_type_name(typeid(*this).name())
|
||||
<< ": item " << i << " is not expected";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!itemLengths[i].validate(list[i].size())) {
|
||||
std::ostringstream error;
|
||||
error << "while parsing " << demangle_type_name(typeid(*this).name());
|
||||
error << ": item " << i << " is expected to be " << itemLengths[i] << " characters long, ";
|
||||
@ -200,7 +222,7 @@ formattable_ptr TotalGenerated::format(formatter::Format format) {
|
||||
}
|
||||
|
||||
|
||||
void SeriesNumber::unpack() {
|
||||
void SerialNumber::unpack() {
|
||||
auto data = getData();
|
||||
|
||||
std::string buf(data, 2);
|
||||
@ -209,9 +231,9 @@ void SeriesNumber::unpack() {
|
||||
id = std::string(data+2, len);
|
||||
}
|
||||
|
||||
formattable_ptr SeriesNumber::format(formatter::Format format) {
|
||||
formattable_ptr SerialNumber::format(formatter::Format format) {
|
||||
RETURN_TABLE({
|
||||
LINE("sn", "Series number", id)
|
||||
LINE("sn", "Serial number", id)
|
||||
});
|
||||
}
|
||||
|
||||
@ -249,7 +271,7 @@ void RatedInformation::unpack() {
|
||||
3, // LLL
|
||||
3, // MMM
|
||||
1, // N
|
||||
2, // OO
|
||||
FieldLength(2, 3), // OO
|
||||
3, // PPP
|
||||
1, // O
|
||||
1, // R
|
||||
@ -276,15 +298,15 @@ void RatedInformation::unpack() {
|
||||
battery_bulk_voltage = stou(list[11]);
|
||||
battery_float_voltage = stou(list[12]);
|
||||
battery_type = static_cast<BatteryType>(stou(list[13]));
|
||||
max_ac_charging_current = stou(list[14]);
|
||||
max_charging_current = stou(list[15]);
|
||||
max_ac_charge_current = stou(list[14]);
|
||||
max_charge_current = stou(list[15]);
|
||||
input_voltage_range = static_cast<InputVoltageRange>(stou(list[16]));
|
||||
output_source_priority = static_cast<OutputModelSetting>(stou(list[17]));
|
||||
charger_source_priority = static_cast<ChargerSourcePriority>(stou(list[18]));
|
||||
output_source_priority = static_cast<OutputSourcePriority>(stou(list[17]));
|
||||
charge_source_priority = static_cast<ChargeSourcePriority>(stou(list[18]));
|
||||
parallel_max_num = stou(list[19]);
|
||||
machine_type = static_cast<MachineType>(stou(list[20]));
|
||||
topology = static_cast<Topology>(stou(list[21]));
|
||||
output_model_setting = static_cast<OutputModelSetting>(stou(list[22]));
|
||||
output_mode = static_cast<OutputMode>(stou(list[22]));
|
||||
solar_power_priority = static_cast<SolarPowerPriority>(stou(list[23]));
|
||||
mppt = list[24];
|
||||
}
|
||||
@ -305,15 +327,15 @@ formattable_ptr RatedInformation::format(formatter::Format format) {
|
||||
LINE("battery_bulk_voltage", "Battery bulk voltage", battery_bulk_voltage / 10.0, Unit::V),
|
||||
LINE("battery_float_voltage", "Battery float voltage", battery_float_voltage / 10.0, Unit::V),
|
||||
LINE("battery_type", "Battery type", battery_type),
|
||||
LINE("max_charging_current", "Max charging current", max_charging_current, Unit::A),
|
||||
LINE("max_ac_charging_current", "Max AC charging current", max_ac_charging_current, Unit::A),
|
||||
LINE("max_charge_current", "Max charge current", max_charge_current, Unit::A),
|
||||
LINE("max_ac_charge_current", "Max AC charge current", max_ac_charge_current, Unit::A),
|
||||
LINE("input_voltage_range", "Input voltage range", input_voltage_range),
|
||||
LINE("output_source_priority", "Output source priority", output_source_priority),
|
||||
LINE("charge_source_priority", "Charge source priority", charger_source_priority),
|
||||
LINE("charge_source_priority", "Charge source priority", charge_source_priority),
|
||||
LINE("parallel_max_num", "Parallel max num", parallel_max_num),
|
||||
LINE("machine_type", "Machine type", machine_type),
|
||||
LINE("topology", "Topology", topology),
|
||||
LINE("output_model_setting", "Output model setting", output_model_setting),
|
||||
LINE("output_mode", "Output mode", output_mode),
|
||||
LINE("solar_power_priority", "Solar power priority", solar_power_priority),
|
||||
LINE("mppt", "MPPT string", mppt)
|
||||
});
|
||||
@ -363,7 +385,7 @@ void GeneralStatus::unpack() {
|
||||
battery_voltage_scc = stou(list[8]);
|
||||
battery_voltage_scc2 = stou(list[9]);
|
||||
battery_discharge_current = stou(list[10]);
|
||||
battery_charging_current = stou(list[11]);
|
||||
battery_charge_current = stou(list[11]);
|
||||
battery_capacity = stou(list[12]);
|
||||
inverter_heat_sink_temp = stou(list[13]);
|
||||
mppt1_charger_temp = stou(list[14]);
|
||||
@ -394,8 +416,8 @@ formattable_ptr GeneralStatus::format(formatter::Format format) {
|
||||
LINE("battery_voltage", "Battery voltage", battery_voltage / 10.0, Unit::V),
|
||||
LINE("battery_voltage_scc", "Battery voltage from SCC", battery_voltage_scc / 10.0, Unit::V),
|
||||
LINE("battery_voltage_scc2", "Battery voltage from SCC2", battery_voltage_scc2 / 10.0, Unit::V),
|
||||
LINE("battery_discharging_current", "Battery discharging current", battery_discharge_current, Unit::A),
|
||||
LINE("battery_charging_current", "Battery charging current", battery_charging_current, Unit::A),
|
||||
LINE("battery_discharge_current", "Battery discharge current", battery_discharge_current, Unit::A),
|
||||
LINE("battery_charge_current", "Battery charge current", battery_charge_current, Unit::A),
|
||||
LINE("battery_capacity", "Battery capacity", battery_capacity, Unit::Percentage),
|
||||
LINE("inverter_heat_sink_temp", "Inverter heat sink temperature", inverter_heat_sink_temp, Unit::Celsius),
|
||||
LINE("mppt1_charger_temp", "MPPT1 charger temperature", mppt1_charger_temp, Unit::Celsius),
|
||||
@ -524,7 +546,7 @@ formattable_ptr FlagsAndStatuses::format(formatter::Format format) {
|
||||
}
|
||||
|
||||
|
||||
void Defaults::unpack() {
|
||||
void RatedDefaults::unpack() {
|
||||
auto list = getList({
|
||||
4, // AAAA
|
||||
3, // BBB
|
||||
@ -560,14 +582,14 @@ void Defaults::unpack() {
|
||||
charging_bulk_voltage = stou(list[5]);
|
||||
battery_recharge_voltage = stou(list[6]);
|
||||
battery_redischarge_voltage = stou(list[7]);
|
||||
max_charging_current = stou(list[8]);
|
||||
max_ac_charging_current = stou(list[9]);
|
||||
max_charge_current = stou(list[8]);
|
||||
max_ac_charge_current = stou(list[9]);
|
||||
battery_type = static_cast<BatteryType>(stou(list[10]));
|
||||
output_source_priority = static_cast<OutputSourcePriority>(stou(list[11]));
|
||||
charger_source_priority = static_cast<ChargerSourcePriority>(stou(list[12]));
|
||||
charge_source_priority = static_cast<ChargeSourcePriority>(stou(list[12]));
|
||||
solar_power_priority = static_cast<SolarPowerPriority>(stou(list[13]));
|
||||
machine_type = static_cast<MachineType>(stou(list[14]));
|
||||
output_model_setting = static_cast<OutputModelSetting>(stou(list[15]));
|
||||
output_mode = static_cast<OutputMode>(stou(list[15]));
|
||||
flag_buzzer = stou(list[16]) > 0;
|
||||
flag_overload_restart = stou(list[17]) > 0;
|
||||
flag_over_temp_restart = stou(list[18]) > 0;
|
||||
@ -578,7 +600,7 @@ void Defaults::unpack() {
|
||||
flag_lcd_escape_to_default_page_after_1min_timeout = stou(list[23]) > 0;
|
||||
}
|
||||
|
||||
formattable_ptr Defaults::format(formatter::Format format) {
|
||||
formattable_ptr RatedDefaults::format(formatter::Format format) {
|
||||
RETURN_TABLE({
|
||||
LINE("ac_output_voltage", "AC output voltage", ac_output_voltage / 10.0, Unit::V),
|
||||
LINE("ac_output_freq", "AC output frequency", ac_output_freq / 10.0, Unit::Hz),
|
||||
@ -586,16 +608,16 @@ formattable_ptr Defaults::format(formatter::Format format) {
|
||||
LINE("battery_under_voltage", "Battery under voltage", battery_under_voltage / 10.0, Unit::V),
|
||||
LINE("battery_bulk_voltage", "Charging bulk voltage", charging_bulk_voltage / 10.0, Unit::V),
|
||||
LINE("battery_float_voltage", "Charging float voltage", charging_float_voltage / 10.0, Unit::V),
|
||||
LINE("battery_recharging_voltage", "Battery re-charging voltage", battery_recharge_voltage / 10.0, Unit::V),
|
||||
LINE("battery_redischarging_voltage", "Battery re-discharging voltage", battery_redischarge_voltage / 10.0, Unit::V),
|
||||
LINE("max_charging_current", "Max charging current", max_charging_current, Unit::A),
|
||||
LINE("max_ac_charging_current", "Max AC charging current", max_ac_charging_current, Unit::A),
|
||||
LINE("battery_recharge_voltage", "Battery re-charge voltage", battery_recharge_voltage / 10.0, Unit::V),
|
||||
LINE("battery_redischarge_voltage", "Battery re-discharge voltage", battery_redischarge_voltage / 10.0, Unit::V),
|
||||
LINE("max_charge_current", "Max charge current", max_charge_current, Unit::A),
|
||||
LINE("max_ac_charge_current", "Max AC charge current", max_ac_charge_current, Unit::A),
|
||||
LINE("battery_type", "Battery type", battery_type),
|
||||
LINE("output_source_priority", "Output source priority", output_source_priority),
|
||||
LINE("charger_source_priority", "Charger source priority", charger_source_priority),
|
||||
LINE("charge_source_priority", "Charge source priority", charge_source_priority),
|
||||
LINE("solar_power_priority", "Solar power priority", solar_power_priority),
|
||||
LINE("machine_type", "Machine type", machine_type),
|
||||
LINE("output_model_setting", "Output model setting", output_model_setting),
|
||||
LINE("output_mode", "Output mode", output_mode),
|
||||
LINE("buzzer_flag", "Buzzer flag", flag_buzzer),
|
||||
LINE("overload_bypass_flag", "Overload bypass function flag", flag_overload_bypass),
|
||||
LINE("escape_to_default_screen_after_1min_timeout_flag", "Escape to default screen after 1min timeout flag", flag_lcd_escape_to_default_page_after_1min_timeout),
|
||||
@ -607,14 +629,14 @@ formattable_ptr Defaults::format(formatter::Format format) {
|
||||
})
|
||||
}
|
||||
|
||||
void AllowedChargingCurrents::unpack() {
|
||||
void AllowedChargeCurrents::unpack() {
|
||||
auto list = getList({});
|
||||
for (const std::string& i: list) {
|
||||
amps.emplace_back(stou(i));
|
||||
}
|
||||
}
|
||||
|
||||
formattable_ptr AllowedChargingCurrents::format(formatter::Format format) {
|
||||
formattable_ptr AllowedChargeCurrents::format(formatter::Format format) {
|
||||
std::vector<formatter::ListItem<VariantHolder>> v;
|
||||
for (const auto& n: amps)
|
||||
v.emplace_back(n);
|
||||
@ -632,27 +654,32 @@ void ParallelRatedInformation::unpack() {
|
||||
20, // CCCCCCCCCCCCCCCCCCCC
|
||||
1, // D
|
||||
3, // EEE
|
||||
2, // FF
|
||||
|
||||
// FF
|
||||
// note: protocol documentation says that the following field is 2 bytes long,
|
||||
// but actual tests of the 6kw unit shows it can be 3 bytes long
|
||||
FieldLength(2, 3),
|
||||
|
||||
1 // G
|
||||
});
|
||||
|
||||
parallel_id_connection_status = static_cast<ParallelConnectionStatus>(stou(list[0]));
|
||||
parallel_connection_status = static_cast<ParallelConnectionStatus>(stou(list[0]));
|
||||
serial_number_valid_length = stou(list[1]);
|
||||
serial_number = std::string(list[2], serial_number_valid_length);
|
||||
charger_source_priority = static_cast<ChargerSourcePriority>(stou(list[3]));
|
||||
max_charging_current = stou(list[4]);
|
||||
max_ac_charging_current = stou(list[5]);
|
||||
output_model_setting = static_cast<OutputModelSetting>(stou(list[6]));
|
||||
serial_number = std::string(list[2], 0, serial_number_valid_length);
|
||||
charge_source_priority = static_cast<ChargeSourcePriority>(stou(list[3]));
|
||||
max_charge_current = stou(list[4]);
|
||||
max_ac_charge_current = stou(list[5]);
|
||||
output_mode = static_cast<OutputMode>(stou(list[6]));
|
||||
}
|
||||
|
||||
formattable_ptr ParallelRatedInformation::format(formatter::Format format) {
|
||||
RETURN_TABLE({
|
||||
LINE("parallel_id_connection_status", "Parallel ID connection status", parallel_id_connection_status),
|
||||
LINE("parallel_connection_status", "Parallel connection status", parallel_connection_status),
|
||||
LINE("serial_number", "Serial number", serial_number),
|
||||
LINE("charger_source_priority", "Charger source priority", charger_source_priority),
|
||||
LINE("max_charging_current", "Max charging current", max_charging_current, Unit::A),
|
||||
LINE("max_ac_charging_current", "Max AC charging current", max_ac_charging_current, Unit::A),
|
||||
LINE("output_model_setting", "Output model setting", output_model_setting),
|
||||
LINE("charge_source_priority", "Charge source priority", charge_source_priority),
|
||||
LINE("max_charge_current", "Max charge current", max_charge_current, Unit::A),
|
||||
LINE("max_ac_charge_current", "Max AC charge current", max_ac_charge_current, Unit::A),
|
||||
LINE("output_mode", "Output mode", output_mode),
|
||||
})
|
||||
}
|
||||
|
||||
@ -682,15 +709,19 @@ void ParallelGeneralStatus::unpack() {
|
||||
4, // TTTT
|
||||
4, // UUUU
|
||||
1, // V
|
||||
// FIXME: marked red in the docs
|
||||
1, // W
|
||||
// FIXME: marked red in the docs
|
||||
1, // X
|
||||
1, // Y
|
||||
1, // Z
|
||||
1, // a
|
||||
3, // bbb. Note: this one is marked in red in the doc. I don't know what that means.
|
||||
});
|
||||
3, // bbb. Note: this one is marked in red in the doc. Apparently it means
|
||||
// that it may be missing on some models, see
|
||||
// https://github.com/gch1p/inverter-tools/issues/1#issuecomment-981158688
|
||||
}, 28);
|
||||
|
||||
parallel_id_connection_status = static_cast<ParallelConnectionStatus>(stou(list[0]));
|
||||
parallel_connection_status = static_cast<ParallelConnectionStatus>(stou(list[0]));
|
||||
work_mode = static_cast<p18::WorkingMode>(stou(list[1]));
|
||||
fault_code = stou(list[2]);
|
||||
grid_voltage = stou(list[3]);
|
||||
@ -705,8 +736,8 @@ void ParallelGeneralStatus::unpack() {
|
||||
total_output_load_percent = stou(list[12]);
|
||||
battery_voltage = stou(list[13]);
|
||||
battery_discharge_current = stou(list[14]);
|
||||
battery_charging_current = stou(list[15]);
|
||||
total_battery_charging_current = stou(list[16]);
|
||||
battery_charge_current = stou(list[15]);
|
||||
total_battery_charge_current = stou(list[16]);
|
||||
battery_capacity = stou(list[17]);
|
||||
pv1_input_power = stou(list[18]);
|
||||
pv2_input_power = stou(list[19]);
|
||||
@ -718,12 +749,15 @@ void ParallelGeneralStatus::unpack() {
|
||||
battery_power_direction = static_cast<BatteryPowerDirection>(stou(list[25]));
|
||||
dc_ac_power_direction = static_cast<DC_AC_PowerDirection>(stou(list[26]));
|
||||
line_power_direction = static_cast<LinePowerDirection>(stou(list[27]));
|
||||
if (list.size() >= 29) {
|
||||
max_temp_present = true;
|
||||
max_temp = stou(list[28]);
|
||||
}
|
||||
}
|
||||
|
||||
formattable_ptr ParallelGeneralStatus::format(formatter::Format format) {
|
||||
RETURN_TABLE({
|
||||
LINE("parallel_id_connection_status", "Parallel ID connection status", parallel_id_connection_status),
|
||||
auto table = new formatter::Table<VariantHolder>(format, {
|
||||
LINE("parallel_connection_status", "Parallel connection status", parallel_connection_status),
|
||||
LINE("mode", "Working mode", work_mode),
|
||||
LINE("fault_code", "Fault code", fault_code),
|
||||
LINE("grid_voltage", "Grid voltage", grid_voltage / 10.0, Unit::V),
|
||||
@ -738,23 +772,32 @@ formattable_ptr ParallelGeneralStatus::format(formatter::Format format) {
|
||||
LINE("total_output_load_percent", "Total output load percent", total_output_load_percent, Unit::Percentage),
|
||||
LINE("battery_voltage", "Battery voltage", battery_voltage / 10.0, Unit::V),
|
||||
LINE("battery_discharge_current", "Battery discharge current", battery_discharge_current, Unit::A),
|
||||
LINE("battery_charging_current", "Battery charging current", battery_charging_current, Unit::A),
|
||||
LINE("pv1_input_power", "PV1 Input power", pv1_input_power, Unit::Wh),
|
||||
LINE("pv2_input_power", "PV2 Input power", pv2_input_power, Unit::Wh),
|
||||
LINE("pv1_input_voltage", "PV1 Input voltage", pv1_input_voltage / 10.0, Unit::V),
|
||||
LINE("pv2_input_voltage", "PV2 Input voltage", pv2_input_voltage / 10.0, Unit::V),
|
||||
LINE("battery_charge_current", "Battery charge current", battery_charge_current, Unit::A),
|
||||
LINE("total_battery_charge_current", "Total battery charge current", total_battery_charge_current, Unit::A),
|
||||
LINE("battery_capacity", "Battery capacity", battery_capacity, Unit::Percentage),
|
||||
LINE("pv1_input_power", "PV1 input power", pv1_input_power, Unit::Wh),
|
||||
LINE("pv2_input_power", "PV2 input power", pv2_input_power, Unit::Wh),
|
||||
LINE("pv1_input_voltage", "PV1 input voltage", pv1_input_voltage / 10.0, Unit::V),
|
||||
LINE("pv2_input_voltage", "PV2 input voltage", pv2_input_voltage / 10.0, Unit::V),
|
||||
LINE("mppt1_charger_status", "MPPT1 charger status", mppt1_charger_status),
|
||||
LINE("mppt2_charger_status", "MPPT2 charger status", mppt2_charger_status),
|
||||
LINE("load_connected", "Load connection", load_connected),
|
||||
LINE("battery_power_direction", "Battery power direction", battery_power_direction),
|
||||
LINE("dc_ac_power_direction", "DC/AC power direction", dc_ac_power_direction),
|
||||
LINE("line_power_direction", "Line power direction", line_power_direction),
|
||||
LINE("max_temp", "Max. temperature", max_temp),
|
||||
})
|
||||
});
|
||||
|
||||
if (max_temp_present) {
|
||||
table->push(
|
||||
LINE("max_temp", "Max. temperature", max_temp)
|
||||
);
|
||||
}
|
||||
|
||||
return std::shared_ptr<formatter::Table<VariantHolder>>(table);
|
||||
}
|
||||
|
||||
|
||||
void ACChargingTimeBucket::unpack() {
|
||||
void ACChargeTimeBucket::unpack() {
|
||||
auto list = getList({4 /* AAAA */, 4 /* BBBB */});
|
||||
|
||||
start_h = stouh(list[0].substr(0, 2));
|
||||
@ -771,7 +814,7 @@ static inline std::string get_time(unsigned short h, unsigned short m) {
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
formattable_ptr ACChargingTimeBucket::format(formatter::Format format) {
|
||||
formattable_ptr ACChargeTimeBucket::format(formatter::Format format) {
|
||||
RETURN_TABLE({
|
||||
LINE("start_time", "Start time", get_time(start_h, start_m)),
|
||||
LINE("end_time", "End time", get_time(end_h, end_m)),
|
||||
|
@ -32,7 +32,7 @@ typedef std::variant<
|
||||
std::string,
|
||||
p18::BatteryType,
|
||||
p18::BatteryPowerDirection,
|
||||
p18::ChargerSourcePriority,
|
||||
p18::ChargeSourcePriority,
|
||||
p18::DC_AC_PowerDirection,
|
||||
p18::InputVoltageRange,
|
||||
p18::LinePowerDirection,
|
||||
@ -40,7 +40,7 @@ typedef std::variant<
|
||||
p18::MPPTChargerStatus,
|
||||
p18::Topology,
|
||||
p18::OutputSourcePriority,
|
||||
p18::OutputModelSetting,
|
||||
p18::OutputMode,
|
||||
p18::ParallelConnectionStatus,
|
||||
p18::SolarPowerPriority,
|
||||
p18::WorkingMode,
|
||||
@ -62,7 +62,7 @@ public:
|
||||
VariantHolder(std::string v) : v_(v) {}
|
||||
VariantHolder(p18::BatteryType v) : v_(v) {}
|
||||
VariantHolder(p18::BatteryPowerDirection v) : v_(v) {}
|
||||
VariantHolder(p18::ChargerSourcePriority v) : v_(v) {}
|
||||
VariantHolder(p18::ChargeSourcePriority v) : v_(v) {}
|
||||
VariantHolder(p18::DC_AC_PowerDirection v) : v_(v) {}
|
||||
VariantHolder(p18::InputVoltageRange v) : v_(v) {}
|
||||
VariantHolder(p18::LinePowerDirection v) : v_(v) {}
|
||||
@ -70,7 +70,7 @@ public:
|
||||
VariantHolder(p18::MPPTChargerStatus v) : v_(v) {}
|
||||
VariantHolder(p18::Topology v) : v_(v) {}
|
||||
VariantHolder(p18::OutputSourcePriority v) : v_(v) {}
|
||||
VariantHolder(p18::OutputModelSetting v) : v_(v) {}
|
||||
VariantHolder(p18::OutputMode v) : v_(v) {}
|
||||
VariantHolder(p18::ParallelConnectionStatus v) : v_(v) {}
|
||||
VariantHolder(p18::SolarPowerPriority v) : v_(v) {}
|
||||
VariantHolder(p18::WorkingMode v) : v_(v) {}
|
||||
@ -89,7 +89,7 @@ public:
|
||||
bool isEnum =
|
||||
std::holds_alternative<p18::BatteryType>(v_) ||
|
||||
std::holds_alternative<p18::BatteryPowerDirection>(v_) ||
|
||||
std::holds_alternative<p18::ChargerSourcePriority>(v_) ||
|
||||
std::holds_alternative<p18::ChargeSourcePriority>(v_) ||
|
||||
std::holds_alternative<p18::DC_AC_PowerDirection>(v_) ||
|
||||
std::holds_alternative<p18::InputVoltageRange>(v_) ||
|
||||
std::holds_alternative<p18::LinePowerDirection>(v_) ||
|
||||
@ -97,7 +97,7 @@ public:
|
||||
std::holds_alternative<p18::MPPTChargerStatus>(v_) ||
|
||||
std::holds_alternative<p18::Topology>(v_) ||
|
||||
std::holds_alternative<p18::OutputSourcePriority>(v_) ||
|
||||
std::holds_alternative<p18::OutputModelSetting>(v_) ||
|
||||
std::holds_alternative<p18::OutputMode>(v_) ||
|
||||
std::holds_alternative<p18::ParallelConnectionStatus>(v_) ||
|
||||
std::holds_alternative<p18::SolarPowerPriority>(v_) ||
|
||||
std::holds_alternative<p18::WorkingMode>(v_) ||
|
||||
@ -124,6 +124,26 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Some helpers
|
||||
*/
|
||||
class FieldLength {
|
||||
protected:
|
||||
size_t min_;
|
||||
size_t max_;
|
||||
|
||||
public:
|
||||
FieldLength(size_t n) : min_(n), max_(n) {}
|
||||
FieldLength(size_t min, size_t max) : min_(min), max_(max) {}
|
||||
|
||||
[[nodiscard]] bool validate(size_t len) const {
|
||||
return len >= min_ && len <= max_;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, FieldLength fl);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base responses
|
||||
*/
|
||||
@ -145,7 +165,7 @@ class GetResponse : public BaseResponse {
|
||||
protected:
|
||||
const char* getData() const;
|
||||
size_t getDataSize() const;
|
||||
std::vector<std::string> getList(std::vector<size_t> itemLengths) const;
|
||||
std::vector<std::string> getList(std::vector<FieldLength> itemLengths, int expectAtLeast = -1) const;
|
||||
|
||||
public:
|
||||
using BaseResponse::BaseResponse;
|
||||
@ -229,7 +249,7 @@ public:
|
||||
using TotalGenerated::TotalGenerated;
|
||||
};
|
||||
|
||||
class SeriesNumber : public GetResponse {
|
||||
class SerialNumber : public GetResponse {
|
||||
public:
|
||||
using GetResponse::GetResponse;
|
||||
void unpack() override;
|
||||
@ -269,15 +289,15 @@ public:
|
||||
unsigned battery_bulk_voltage; /* unit: 0.1V */
|
||||
unsigned battery_float_voltage; /* unit: 0.1V */
|
||||
p18::BatteryType battery_type;
|
||||
unsigned max_ac_charging_current; /* unit: A */
|
||||
unsigned max_charging_current; /* unit: A */
|
||||
unsigned max_ac_charge_current; /* unit: A */
|
||||
unsigned max_charge_current; /* unit: A */
|
||||
p18::InputVoltageRange input_voltage_range;
|
||||
p18::OutputModelSetting output_source_priority;
|
||||
p18::ChargerSourcePriority charger_source_priority;
|
||||
p18::OutputSourcePriority output_source_priority;
|
||||
p18::ChargeSourcePriority charge_source_priority;
|
||||
unsigned parallel_max_num;
|
||||
p18::MachineType machine_type;
|
||||
p18::Topology topology;
|
||||
p18::OutputModelSetting output_model_setting;
|
||||
p18::OutputMode output_mode;
|
||||
p18::SolarPowerPriority solar_power_priority;
|
||||
std::string mppt;
|
||||
};
|
||||
@ -299,7 +319,7 @@ public:
|
||||
unsigned battery_voltage_scc; /* unit: 0.1V */
|
||||
unsigned battery_voltage_scc2; /* unit: 0.1V */
|
||||
unsigned battery_discharge_current; /* unit: A */
|
||||
unsigned battery_charging_current; /* unit: A */
|
||||
unsigned battery_charge_current; /* unit: A */
|
||||
unsigned battery_capacity; /* unit: % */
|
||||
unsigned inverter_heat_sink_temp; /* unit: C */
|
||||
unsigned mppt1_charger_temp; /* unit: C */
|
||||
@ -369,7 +389,7 @@ public:
|
||||
char reserved = '0';
|
||||
};
|
||||
|
||||
class Defaults : public GetResponse {
|
||||
class RatedDefaults : public GetResponse {
|
||||
public:
|
||||
using GetResponse::GetResponse;
|
||||
void unpack() override;
|
||||
@ -383,14 +403,14 @@ public:
|
||||
unsigned charging_bulk_voltage = 0;
|
||||
unsigned battery_recharge_voltage = 0;
|
||||
unsigned battery_redischarge_voltage = 0;
|
||||
unsigned max_charging_current = 0;
|
||||
unsigned max_ac_charging_current = 0;
|
||||
unsigned max_charge_current = 0;
|
||||
unsigned max_ac_charge_current = 0;
|
||||
p18::BatteryType battery_type = static_cast<BatteryType>(0);
|
||||
p18::OutputSourcePriority output_source_priority = static_cast<OutputSourcePriority>(0);
|
||||
p18::ChargerSourcePriority charger_source_priority = static_cast<ChargerSourcePriority>(0);
|
||||
p18::ChargeSourcePriority charge_source_priority = static_cast<ChargeSourcePriority>(0);
|
||||
p18::SolarPowerPriority solar_power_priority = static_cast<SolarPowerPriority>(0);
|
||||
p18::MachineType machine_type = static_cast<MachineType>(0);
|
||||
p18::OutputModelSetting output_model_setting = static_cast<OutputModelSetting>(0);
|
||||
p18::OutputMode output_mode = static_cast<OutputMode>(0);
|
||||
bool flag_buzzer = false;
|
||||
bool flag_overload_restart = false;
|
||||
bool flag_over_temp_restart = false;
|
||||
@ -401,7 +421,7 @@ public:
|
||||
bool flag_lcd_escape_to_default_page_after_1min_timeout = false;
|
||||
};
|
||||
|
||||
class AllowedChargingCurrents : public GetResponse {
|
||||
class AllowedChargeCurrents : public GetResponse {
|
||||
public:
|
||||
using GetResponse::GetResponse;
|
||||
void unpack() override;
|
||||
@ -410,9 +430,9 @@ public:
|
||||
std::vector<unsigned> amps;
|
||||
};
|
||||
|
||||
class AllowedACChargingCurrents : public AllowedChargingCurrents {
|
||||
class AllowedACChargeCurrents : public AllowedChargeCurrents {
|
||||
public:
|
||||
using AllowedChargingCurrents::AllowedChargingCurrents;
|
||||
using AllowedChargeCurrents::AllowedChargeCurrents;
|
||||
};
|
||||
|
||||
class ParallelRatedInformation : public GetResponse {
|
||||
@ -421,13 +441,13 @@ public:
|
||||
void unpack() override;
|
||||
formattable_ptr format(formatter::Format format) override;
|
||||
|
||||
p18::ParallelConnectionStatus parallel_id_connection_status = static_cast<ParallelConnectionStatus>(0);
|
||||
p18::ParallelConnectionStatus parallel_connection_status = static_cast<ParallelConnectionStatus>(0);
|
||||
unsigned serial_number_valid_length = 0;
|
||||
std::string serial_number;
|
||||
p18::ChargerSourcePriority charger_source_priority = static_cast<ChargerSourcePriority>(0);
|
||||
unsigned max_ac_charging_current = 0; // unit: A
|
||||
unsigned max_charging_current = 0; // unit: A
|
||||
p18::OutputModelSetting output_model_setting = static_cast<OutputModelSetting>(0);
|
||||
p18::ChargeSourcePriority charge_source_priority = static_cast<ChargeSourcePriority>(0);
|
||||
unsigned max_ac_charge_current = 0; // unit: A
|
||||
unsigned max_charge_current = 0; // unit: A
|
||||
p18::OutputMode output_mode = static_cast<OutputMode>(0);
|
||||
};
|
||||
|
||||
class ParallelGeneralStatus : public GetResponse {
|
||||
@ -436,7 +456,7 @@ public:
|
||||
void unpack() override;
|
||||
formattable_ptr format(formatter::Format format) override;
|
||||
|
||||
p18::ParallelConnectionStatus parallel_id_connection_status;
|
||||
p18::ParallelConnectionStatus parallel_connection_status;
|
||||
p18::WorkingMode work_mode;
|
||||
unsigned fault_code;
|
||||
unsigned grid_voltage; /* unit: 0.1V */
|
||||
@ -451,8 +471,8 @@ public:
|
||||
unsigned total_output_load_percent; /* unit: % */
|
||||
unsigned battery_voltage; /* unit: 0.1V */
|
||||
unsigned battery_discharge_current; /* unit: A */
|
||||
unsigned battery_charging_current; /* unit: A */
|
||||
unsigned total_battery_charging_current; /* unit: A */
|
||||
unsigned battery_charge_current; /* unit: A */
|
||||
unsigned total_battery_charge_current; /* unit: A */
|
||||
unsigned battery_capacity; /* unit: % */
|
||||
unsigned pv1_input_power; /* unit: W */
|
||||
unsigned pv2_input_power; /* unit: W */
|
||||
@ -464,10 +484,12 @@ public:
|
||||
p18::BatteryPowerDirection battery_power_direction;
|
||||
p18::DC_AC_PowerDirection dc_ac_power_direction;
|
||||
p18::LinePowerDirection line_power_direction;
|
||||
|
||||
bool max_temp_present = false;
|
||||
unsigned max_temp; /* unit: C */
|
||||
};
|
||||
|
||||
class ACChargingTimeBucket : public GetResponse {
|
||||
class ACChargeTimeBucket : public GetResponse {
|
||||
public:
|
||||
using GetResponse::GetResponse;
|
||||
void unpack() override;
|
||||
@ -479,9 +501,9 @@ public:
|
||||
unsigned short end_m = 0;
|
||||
};
|
||||
|
||||
class ACLoadsSupplyTimeBucket : public ACChargingTimeBucket {
|
||||
class ACSupplyTimeBucket : public ACChargeTimeBucket {
|
||||
public:
|
||||
using ACChargingTimeBucket::ACChargingTimeBucket;
|
||||
using ACChargeTimeBucket::ACChargeTimeBucket;
|
||||
};
|
||||
|
||||
} // namespace p18
|
||||
|
@ -17,41 +17,41 @@ enum class CommandType {
|
||||
GetYearGenerated,
|
||||
GetMonthGenerated,
|
||||
GetDayGenerated,
|
||||
GetSeriesNumber,
|
||||
GetSerialNumber,
|
||||
GetCPUVersion,
|
||||
GetRatedInformation,
|
||||
GetGeneralStatus,
|
||||
GetWorkingMode,
|
||||
GetFaultsAndWarnings,
|
||||
GetFlagsAndStatuses,
|
||||
GetDefaults,
|
||||
GetAllowedChargingCurrents,
|
||||
GetAllowedACChargingCurrents,
|
||||
GetRatedDefaults,
|
||||
GetAllowedChargeCurrents,
|
||||
GetAllowedACChargeCurrents,
|
||||
GetParallelRatedInformation,
|
||||
GetParallelGeneralStatus,
|
||||
GetACChargingTimeBucket,
|
||||
GetACLoadsSupplyTimeBucket,
|
||||
SetLoads = 100,
|
||||
GetACChargeTimeBucket,
|
||||
GetACSupplyTimeBucket,
|
||||
SetACSupply = 100,
|
||||
SetFlag,
|
||||
SetDefaults,
|
||||
SetBatteryMaxChargingCurrent,
|
||||
SetBatteryMaxACChargingCurrent,
|
||||
SetBatteryMaxChargeCurrent,
|
||||
SetBatteryMaxACChargeCurrent,
|
||||
SetACOutputFreq,
|
||||
SetBatteryMaxChargingVoltage,
|
||||
SetACOutputRatedVoltage,
|
||||
SetBatteryMaxChargeVoltage,
|
||||
SetACOutputVoltage,
|
||||
SetOutputSourcePriority,
|
||||
SetBatteryChargingThresholds, /* Battery re-charging and re-discharing voltage when utility is available */
|
||||
SetChargingSourcePriority,
|
||||
SetBatteryChargeThresholds, /* Battery re-charge and re-discharge voltage when utility is available */
|
||||
SetChargeSourcePriority,
|
||||
SetSolarPowerPriority,
|
||||
SetACInputVoltageRange,
|
||||
SetBatteryType,
|
||||
SetOutputModel,
|
||||
SetOutputMode,
|
||||
SetBatteryCutOffVoltage,
|
||||
SetSolarConfig,
|
||||
ClearGenerated,
|
||||
SetDateTime,
|
||||
SetACChargingTimeBucket,
|
||||
SetACLoadsSupplyTimeBucket,
|
||||
SetACChargeTimeBucket,
|
||||
SetACSupplyTimeBucket,
|
||||
};
|
||||
|
||||
enum class BatteryType {
|
||||
@ -73,12 +73,12 @@ enum class OutputSourcePriority {
|
||||
};
|
||||
ENUM_STR(OutputSourcePriority);
|
||||
|
||||
enum class ChargerSourcePriority {
|
||||
enum class ChargeSourcePriority {
|
||||
SolarFirst = 0,
|
||||
SolarAndUtility = 1,
|
||||
SolarOnly = 2,
|
||||
};
|
||||
ENUM_STR(ChargerSourcePriority);
|
||||
ENUM_STR(ChargeSourcePriority);
|
||||
|
||||
enum class MachineType {
|
||||
OffGridTie = 0,
|
||||
@ -92,14 +92,14 @@ enum class Topology {
|
||||
};
|
||||
ENUM_STR(Topology);
|
||||
|
||||
enum class OutputModelSetting {
|
||||
SingleModule = 0,
|
||||
enum class OutputMode {
|
||||
SingleOutput = 0,
|
||||
ParallelOutput = 1,
|
||||
Phase1OfThreePhaseOutput = 2,
|
||||
Phase2OfThreePhaseOutput = 3,
|
||||
Phase3OfThreePhaseOutput = 4,
|
||||
Phase_1_of_3 = 2,
|
||||
Phase_2_of_3 = 3,
|
||||
Phase_3_of_3 = 4,
|
||||
};
|
||||
ENUM_STR(OutputModelSetting);
|
||||
ENUM_STR(OutputMode);
|
||||
|
||||
enum class SolarPowerPriority {
|
||||
BatteryLoadUtility = 0,
|
||||
|
@ -72,8 +72,11 @@ public:
|
||||
static u16 GET_HID_REPORT_SIZE(size_t size);
|
||||
|
||||
USBDevice(u16 vendorId, u16 productId);
|
||||
explicit USBDevice(const std::string& path);
|
||||
~USBDevice();
|
||||
|
||||
static inline void init();
|
||||
|
||||
size_t read(u8* buf, size_t bufSize) override;
|
||||
size_t write(const u8* data, size_t dataSize) override;
|
||||
};
|
||||
|
@ -12,14 +12,24 @@
|
||||
namespace voltronic {
|
||||
|
||||
USBDevice::USBDevice(u16 vendorId, u16 productId) {
|
||||
if (hid_init() != 0)
|
||||
throw DeviceError("hidapi initialization failure");
|
||||
|
||||
init();
|
||||
device_ = hid_open(vendorId, productId, nullptr);
|
||||
if (!device_)
|
||||
throw DeviceError("failed to create hidapi device");
|
||||
}
|
||||
|
||||
USBDevice::USBDevice(const std::string& path) {
|
||||
init();
|
||||
device_ = hid_open_path(path.c_str());
|
||||
if (!device_)
|
||||
throw DeviceError("failed to create hidapi device");
|
||||
}
|
||||
|
||||
void USBDevice::init() {
|
||||
if (hid_init() != 0)
|
||||
throw DeviceError("hidapi initialization failure");
|
||||
}
|
||||
|
||||
USBDevice::~USBDevice() {
|
||||
if (device_)
|
||||
hid_close(device_);
|
||||
|
Loading…
x
Reference in New Issue
Block a user