// SPDX-License-Identifier: BSD-3-Clause #ifndef INVERTER_TOOLS_P18_RESPONSE_H #define INVERTER_TOOLS_P18_RESPONSE_H #include #include #include #include #include #include "types.h" #include "../formatter/formatter.h" #include "../protocol/response.h" namespace p18::response_type { using protocol::BaseResponse; using nlohmann::json; typedef std::shared_ptr formattable_ptr; /** * Value holder for the formatter module */ typedef std::variant< unsigned, unsigned short, unsigned long, bool, double, std::string, p18::BatteryType, p18::BatteryPowerDirection, p18::ChargerSourcePriority, p18::DC_AC_PowerDirection, p18::InputVoltageRange, p18::LinePowerDirection, p18::MachineType, p18::MPPTChargerStatus, p18::Topology, p18::OutputSourcePriority, p18::OutputModelSetting, p18::ParallelConnectionStatus, p18::SolarPowerPriority, p18::WorkingMode, p18::LoadConnectionStatus, p18::ConfigurationStatus > Variant; class VariantHolder { private: Variant v_; public: VariantHolder(unsigned v) : v_(v) {} VariantHolder(unsigned short v) : v_(v) {} VariantHolder(unsigned long v) : v_(v) {} VariantHolder(bool v) : v_(v) {} VariantHolder(double v) : v_(v) {} 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::DC_AC_PowerDirection v) : v_(v) {} VariantHolder(p18::InputVoltageRange v) : v_(v) {} VariantHolder(p18::LinePowerDirection v) : v_(v) {} VariantHolder(p18::MachineType v) : v_(v) {} 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::ParallelConnectionStatus v) : v_(v) {} VariantHolder(p18::SolarPowerPriority v) : v_(v) {} VariantHolder(p18::WorkingMode v) : v_(v) {} VariantHolder(p18::LoadConnectionStatus v) : v_(v) {} VariantHolder(p18::ConfigurationStatus v) : v_(v) {} friend std::ostream &operator<<(std::ostream &os, VariantHolder const& ref) { std::visit([&os](const auto& elem) { os << elem; }, ref.v_); return os; } inline json toJSON() const { json j; bool isEnum = std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_) || std::holds_alternative(v_); std::visit([&j, &isEnum](const auto& elem) { if (isEnum) j = formatter::to_str(elem); else j = elem; }, v_); return j; } inline json toSimpleJSON() const { json j; std::visit([&j](const auto& elem) { j = elem; }, v_); return j; } }; /** * 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 */ class BaseResponse { protected: std::shared_ptr raw_; size_t rawSize_; public: BaseResponse(std::shared_ptr raw, size_t rawSize); virtual ~BaseResponse() = default; virtual bool validate() = 0; virtual void unpack() = 0; virtual formattable_ptr format(formatter::Format format) = 0; }; class GetResponse : public BaseResponse { protected: const char* getData() const; size_t getDataSize() const; std::vector getList(std::vector itemLengths, int expectAtLeast = -1) const; public: using BaseResponse::BaseResponse; bool validate() override; }; class SetResponse : public BaseResponse { public: using BaseResponse::BaseResponse; void unpack() override; bool validate() override; formattable_ptr format(formatter::Format format) override; bool get(); }; /** * Actual typed responses */ class ProtocolID : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; unsigned id = 0; }; class CurrentTime : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; unsigned year = 0; unsigned short month = 0; unsigned short day = 0; unsigned short hour = 0; unsigned short minute = 0; unsigned short second = 0; }; class TotalGenerated : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; unsigned long wh = 0; }; class YearGenerated : public TotalGenerated { public: using TotalGenerated::TotalGenerated; }; class MonthGenerated : public TotalGenerated { public: using TotalGenerated::TotalGenerated; }; class DayGenerated : public TotalGenerated { public: using TotalGenerated::TotalGenerated; }; class SeriesNumber : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; std::string id; }; class CPUVersion : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; std::string main_cpu_version; std::string slave1_cpu_version; std::string slave2_cpu_version; }; class RatedInformation : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; unsigned ac_input_rating_voltage; /* unit: 0.1V */ unsigned ac_input_rating_current; /* unit: 0.1A */ unsigned ac_output_rating_voltage; /* unit: 0.1A */ unsigned ac_output_rating_freq; /* unit: 0.1Hz */ unsigned ac_output_rating_current; /* unit: 0.1A */ unsigned ac_output_rating_apparent_power; /* unit: VA */ unsigned ac_output_rating_active_power; /* unit: W */ unsigned battery_rating_voltage; /* unit: 0.1V */ unsigned battery_recharge_voltage; /* unit: 0.1V */ unsigned battery_redischarge_voltage; /* unit: 0.1V */ unsigned battery_under_voltage; /* unit: 0.1V */ 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 */ p18::InputVoltageRange input_voltage_range; p18::OutputModelSetting output_source_priority; p18::ChargerSourcePriority charger_source_priority; unsigned parallel_max_num; p18::MachineType machine_type; p18::Topology topology; p18::OutputModelSetting output_model_setting; p18::SolarPowerPriority solar_power_priority; std::string mppt; }; class GeneralStatus : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; unsigned grid_voltage; /* unit: 0.1V */ unsigned grid_freq; /* unit: 0.1Hz */ unsigned ac_output_voltage; /* unit: 0.1V */ unsigned ac_output_freq; /* unit: 0.1Hz */ unsigned ac_output_apparent_power; /* unit: VA */ unsigned ac_output_active_power; /* unit: W */ unsigned output_load_percent; /* unit: % */ unsigned battery_voltage; /* unit: 0.1V */ 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_capacity; /* unit: % */ unsigned inverter_heat_sink_temp; /* unit: C */ unsigned mppt1_charger_temp; /* unit: C */ unsigned mppt2_charger_temp; /* unit: C */ unsigned pv1_input_power; /* unit: W */ unsigned pv2_input_power; /* unit: W */ unsigned pv1_input_voltage; /* unit: 0.1V */ unsigned pv2_input_voltage; /* unit: 0.1V */ p18::ConfigurationStatus configuration_status; p18::MPPTChargerStatus mppt1_charger_status; p18::MPPTChargerStatus mppt2_charger_status; p18::LoadConnectionStatus load_connected; p18::BatteryPowerDirection battery_power_direction; p18::DC_AC_PowerDirection dc_ac_power_direction; p18::LinePowerDirection line_power_direction; unsigned local_parallel_id; /* 0 .. (parallel number - 1) */ }; class WorkingMode : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; p18::WorkingMode mode = static_cast(0); }; class FaultsAndWarnings : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; unsigned fault_code = 0; bool line_fail = false; bool output_circuit_short = false; bool inverter_over_temperature = false; bool fan_lock = false; bool battery_voltage_high = false; bool battery_low = false; bool battery_under = false; bool over_load = false; bool eeprom_fail = false; bool power_limit = false; bool pv1_voltage_high = false; bool pv2_voltage_high = false; bool mppt1_overload_warning = false; bool mppt2_overload_warning = false; bool battery_too_low_to_charge_for_scc1 = false; bool battery_too_low_to_charge_for_scc2 = false; }; class FlagsAndStatuses : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; bool buzzer = false; bool overload_bypass = false; bool lcd_escape_to_default_page_after_1min_timeout = false; bool overload_restart = false; bool over_temp_restart = false; bool backlight_on = false; bool alarm_on_primary_source_interrupt = false; bool fault_code_record = false; char reserved = '0'; }; class Defaults : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; unsigned ac_output_voltage = 0; /* unit: 0.1V */ unsigned ac_output_freq = 0; p18::InputVoltageRange ac_input_voltage_range = static_cast(0); unsigned battery_under_voltage = 0; unsigned charging_float_voltage = 0; 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; p18::BatteryType battery_type = static_cast(0); p18::OutputSourcePriority output_source_priority = static_cast(0); p18::ChargerSourcePriority charger_source_priority = static_cast(0); p18::SolarPowerPriority solar_power_priority = static_cast(0); p18::MachineType machine_type = static_cast(0); p18::OutputModelSetting output_model_setting = static_cast(0); bool flag_buzzer = false; bool flag_overload_restart = false; bool flag_over_temp_restart = false; bool flag_backlight_on = false; bool flag_alarm_on_primary_source_interrupt = false; bool flag_fault_code_record = false; bool flag_overload_bypass = false; bool flag_lcd_escape_to_default_page_after_1min_timeout = false; }; class AllowedChargingCurrents : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; std::vector amps; }; class AllowedACChargingCurrents : public AllowedChargingCurrents { public: using AllowedChargingCurrents::AllowedChargingCurrents; }; class ParallelRatedInformation : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; p18::ParallelConnectionStatus parallel_id_connection_status = static_cast(0); unsigned serial_number_valid_length = 0; std::string serial_number; p18::ChargerSourcePriority charger_source_priority = static_cast(0); unsigned max_ac_charging_current = 0; // unit: A unsigned max_charging_current = 0; // unit: A p18::OutputModelSetting output_model_setting = static_cast(0); }; class ParallelGeneralStatus : public GetResponse { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; p18::ParallelConnectionStatus parallel_id_connection_status; p18::WorkingMode work_mode; unsigned fault_code; unsigned grid_voltage; /* unit: 0.1V */ unsigned grid_freq; /* unit: 0.1Hz */ unsigned ac_output_voltage; /* unit: 0.1V */ unsigned ac_output_freq; /* unit: 0.1Hz */ unsigned ac_output_apparent_power; /* unit: VA */ unsigned ac_output_active_power; /* unit: W */ unsigned total_ac_output_apparent_power; /* unit: VA */ unsigned total_ac_output_active_power; /* unit: W */ unsigned output_load_percent; /* unit: % */ 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_capacity; /* unit: % */ unsigned pv1_input_power; /* unit: W */ unsigned pv2_input_power; /* unit: W */ unsigned pv1_input_voltage; /* unit: 0.1V */ unsigned pv2_input_voltage; /* unit: 0.1V */ p18::MPPTChargerStatus mppt1_charger_status; p18::MPPTChargerStatus mppt2_charger_status; p18::LoadConnectionStatus load_connected; 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 { public: using GetResponse::GetResponse; void unpack() override; formattable_ptr format(formatter::Format format) override; unsigned short start_h = 0; unsigned short start_m = 0; unsigned short end_h = 0; unsigned short end_m = 0; }; class ACLoadsSupplyTimeBucket : public ACChargingTimeBucket { public: using ACChargingTimeBucket::ACChargingTimeBucket; }; } // namespace protocol_18 #endif //INVERTER_TOOLS_P18_RESPONSE_H