aboutsummaryrefslogtreecommitdiff
path: root/src/protocol_18/response.h
blob: 239c474bcae7480d1fef97fbf9b0e01f8a9d7a16 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
// SPDX-License-Identifier: BSD-3-Clause

#ifndef INVERTER_TOOLS_P18_RESPONSE_H
#define INVERTER_TOOLS_P18_RESPONSE_H

#include <string>
#include <vector>
#include <memory>
#include <variant>
#include <nlohmann/json.hpp>

#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<formatter::Formattable> 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<p18::BatteryType>(v_) ||
            std::holds_alternative<p18::BatteryPowerDirection>(v_) ||
            std::holds_alternative<p18::ChargerSourcePriority>(v_) ||
            std::holds_alternative<p18::DC_AC_PowerDirection>(v_) ||
            std::holds_alternative<p18::InputVoltageRange>(v_) ||
            std::holds_alternative<p18::LinePowerDirection>(v_) ||
            std::holds_alternative<p18::MachineType>(v_) ||
            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::ParallelConnectionStatus>(v_) ||
            std::holds_alternative<p18::SolarPowerPriority>(v_) ||
            std::holds_alternative<p18::WorkingMode>(v_) ||
            std::holds_alternative<p18::LoadConnectionStatus>(v_) ||
            std::holds_alternative<p18::ConfigurationStatus>(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<char> raw_;
    size_t rawSize_;

public:
    BaseResponse(std::shared_ptr<char> 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<std::string> getList(std::vector<FieldLength> 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<p18::WorkingMode>(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<InputVoltageRange>(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<BatteryType>(0);
    p18::OutputSourcePriority output_source_priority = static_cast<OutputSourcePriority>(0);
    p18::ChargerSourcePriority charger_source_priority = static_cast<ChargerSourcePriority>(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);
    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<unsigned> 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<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);
};

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