Skip to content

Commit c3115de

Browse files
committed
meters-sun-spec: Add support for battery base model 802
1 parent 5840473 commit c3115de

File tree

4 files changed

+196
-3
lines changed

4 files changed

+196
-3
lines changed

software/src/modules/meters_sun_spec/models/generate_from_reference.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
sys.exit(1)
1818

1919
xlsx_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "..", "..", "..", "..", "..", "wallbox", "sunspec", "SunSpec_Information_Model_Reference_20211209.xlsx")
20-
model_ids = [1, 101, 102, 103, 111, 112, 113, 201, 202, 203, 204, 211, 212, 213, 214, 701, 713, 714]
20+
model_ids = [1, 101, 102, 103, 111, 112, 113, 201, 202, 203, 204, 211, 212, 213, 214, 701, 713, 714, 802]
2121

2222
value_id_mappings_inverter = {
2323
"A" : [ "CurrentLSumExport", None ],
@@ -207,6 +207,13 @@
207207
"SoC" : [ "StateOfCharge", None ],
208208
}
209209

210+
value_id_mappings_battery = {
211+
"V" : [ "VoltageDC", None ],
212+
"A" : [ "CurrentDCChaDisDiff", None ],
213+
"W" : [ "PowerDCChaDisDiff", None ],
214+
"SoC" : [ "StateOfCharge", None ],
215+
}
216+
210217
# Unmapped SunSpec IDs
211218
# "ID" : None,
212219
# "L" : None,
@@ -287,6 +294,8 @@
287294
value_id_mappings = value_id_mappings_meter
288295
elif model_id >= 700 and model_id <= 799:
289296
value_id_mappings = value_id_mappings_der
297+
elif model_id >= 800 and model_id <= 899:
298+
value_id_mappings = value_id_mappings_battery
290299
else:
291300
print(f"No value ID mappings available for model ID {model_id}.", file=sys.stderr)
292301
exit(1)
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// WARNING: This file is generated.
2+
3+
#pragma once
4+
5+
#include <stdint.h>
6+
#include <stdlib.h>
7+
8+
#if defined(__GNUC__)
9+
#pragma GCC diagnostic push
10+
#include "gcc_warnings.h"
11+
#pragma GCC diagnostic ignored "-Wattributes"
12+
#endif
13+
14+
// ========================
15+
// 802 - Battery Base Model
16+
// ========================
17+
18+
struct SunSpecBatteryBaseModelModel802_s {
19+
uint16_t ID; // 0
20+
uint16_t L; // 1
21+
uint16_t AHRtg; // 2
22+
uint16_t WHRtg; // 3
23+
uint16_t WChaRteMax; // 4
24+
uint16_t WDisChaRteMax; // 5
25+
uint16_t DisChaRte; // 6
26+
uint16_t SoCMax; // 7
27+
uint16_t SoCMin; // 8
28+
uint16_t SocRsvMax; // 9
29+
uint16_t SoCRsvMin; // 10
30+
uint16_t SoC; // 11
31+
uint16_t DoD; // 12
32+
uint16_t SoH; // 13
33+
[[gnu::packed]] uint32_t NCyc; // 14
34+
uint16_t ChaSt; // 16
35+
uint16_t LocRemCtl; // 17
36+
uint16_t Hb; // 18
37+
uint16_t CtrlHb; // 19
38+
uint16_t AlmRst; // 20
39+
uint16_t Typ; // 21
40+
uint16_t State; // 22
41+
uint16_t StateVnd; // 23
42+
[[gnu::packed]] uint32_t WarrDt; // 24
43+
[[gnu::packed]] uint32_t Evt1; // 26
44+
[[gnu::packed]] uint32_t Evt2; // 28
45+
[[gnu::packed]] uint32_t EvtVnd1; // 30
46+
[[gnu::packed]] uint32_t EvtVnd2; // 32
47+
uint16_t V; // 34
48+
uint16_t VMax; // 35
49+
uint16_t VMin; // 36
50+
uint16_t CellVMax; // 37
51+
uint16_t CellVMaxStr; // 38
52+
uint16_t CellVMaxMod; // 39
53+
uint16_t CellVMin; // 40
54+
uint16_t CellVMinStr; // 41
55+
uint16_t CellVMinMod; // 42
56+
uint16_t CellVAvg; // 43
57+
int16_t A; // 44
58+
uint16_t AChaMax; // 45
59+
uint16_t ADisChaMax; // 46
60+
int16_t W; // 47
61+
uint16_t ReqInvState; // 48
62+
int16_t ReqW; // 49
63+
uint16_t SetOp; // 50
64+
uint16_t SetInvState; // 51
65+
int16_t AHRtg_SF; // 52
66+
int16_t WHRtg_SF; // 53
67+
int16_t WChaDisChaMax_SF; // 54
68+
int16_t DisChaRte_SF; // 55
69+
int16_t SoC_SF; // 56
70+
int16_t DoD_SF; // 57
71+
int16_t SoH_SF; // 58
72+
int16_t V_SF; // 59
73+
int16_t CellV_SF; // 60
74+
int16_t A_SF; // 61
75+
int16_t AMax_SF; // 62
76+
int16_t W_SF; // 63
77+
};
78+
79+
#define SUNSPEC_MODEL_802_NAME "Battery Base Model"
80+
81+
// Total size in bytes, includes ID and length registers.
82+
#define SUNSPEC_MODEL_802_SIZE (128)
83+
84+
// Register count without ID and length registers, should match content of length register.
85+
#define SUNSPEC_MODEL_802_LENGTH (62)
86+
87+
union SunSpecBatteryBaseModelModel802_u {
88+
struct SunSpecBatteryBaseModelModel802_s model;
89+
uint16_t registers[SUNSPEC_MODEL_802_SIZE / sizeof(uint16_t)];
90+
};
91+
92+
static_assert(sizeof(SunSpecBatteryBaseModelModel802_s) == 128, "Incorrect Battery Base Model length.");
93+
static_assert(sizeof(SunSpecBatteryBaseModelModel802_u) == 128, "Incorrect Battery Base Model length.");
94+
static_assert(sizeof(static_cast<SunSpecBatteryBaseModelModel802_u *>(nullptr)->registers) == 128, "Incorrect Battery Base Model length.");
95+
96+
#if defined(__GNUC__)
97+
#pragma GCC diagnostic pop
98+
#endif

software/src/modules/meters_sun_spec/models/model_parser_gen.cpp

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8231,9 +8231,94 @@ static const MetersSunSpecParser::ModelData model_714_data = {
82318231
}
82328232
};
82338233

8234+
// ========================
8235+
// 802 - Battery Base Model
8236+
// ========================
8237+
8238+
#include "model_802.h"
8239+
8240+
static float get_model_802_SoC(const void *register_data, uint32_t quirks, bool detection)
8241+
{
8242+
const struct SunSpecBatteryBaseModelModel802_s *model = static_cast<const struct SunSpecBatteryBaseModelModel802_s *>(register_data);
8243+
uint16_t val = model->SoC;
8244+
if (val == UINT16_MAX) return NAN;
8245+
float fval = static_cast<float>(val);
8246+
fval *= get_sun_spec_scale_factor(model->SoC_SF);
8247+
return fval;
8248+
}
8249+
8250+
static float get_model_802_V(const void *register_data, uint32_t quirks, bool detection)
8251+
{
8252+
const struct SunSpecBatteryBaseModelModel802_s *model = static_cast<const struct SunSpecBatteryBaseModelModel802_s *>(register_data);
8253+
uint16_t val = model->V;
8254+
if (val == UINT16_MAX) return NAN;
8255+
float fval = static_cast<float>(val);
8256+
fval *= get_sun_spec_scale_factor(model->V_SF);
8257+
return fval;
8258+
}
8259+
8260+
static float get_model_802_A(const void *register_data, uint32_t quirks, bool detection)
8261+
{
8262+
const struct SunSpecBatteryBaseModelModel802_s *model = static_cast<const struct SunSpecBatteryBaseModelModel802_s *>(register_data);
8263+
int16_t val = model->A;
8264+
if (val == INT16_MIN) return NAN;
8265+
float fval = static_cast<float>(val);
8266+
fval *= get_sun_spec_scale_factor(model->A_SF);
8267+
return fval;
8268+
}
8269+
8270+
static float get_model_802_W(const void *register_data, uint32_t quirks, bool detection)
8271+
{
8272+
const struct SunSpecBatteryBaseModelModel802_s *model = static_cast<const struct SunSpecBatteryBaseModelModel802_s *>(register_data);
8273+
int16_t val = model->W;
8274+
if (val == INT16_MIN) return NAN;
8275+
float fval = static_cast<float>(val);
8276+
fval *= get_sun_spec_scale_factor(model->W_SF);
8277+
return fval;
8278+
}
8279+
8280+
static bool model_802_validator(const uint16_t * const register_data[2])
8281+
{
8282+
const SunSpecBatteryBaseModelModel802_s *block0 = reinterpret_cast<const SunSpecBatteryBaseModelModel802_s *>(register_data[0]);
8283+
const SunSpecBatteryBaseModelModel802_s *block1 = reinterpret_cast<const SunSpecBatteryBaseModelModel802_s *>(register_data[1]);
8284+
if (block0->ID != 802) return false;
8285+
if (block1->ID != 802) return false;
8286+
if (block0->L != 62) return false;
8287+
if (block1->L != 62) return false;
8288+
if (block0->AHRtg_SF != block1->AHRtg_SF) return false;
8289+
if (block0->WHRtg_SF != block1->WHRtg_SF) return false;
8290+
if (block0->WChaDisChaMax_SF != block1->WChaDisChaMax_SF) return false;
8291+
if (block0->DisChaRte_SF != block1->DisChaRte_SF) return false;
8292+
if (block0->SoC_SF != block1->SoC_SF) return false;
8293+
if (block0->DoD_SF != block1->DoD_SF) return false;
8294+
if (block0->SoH_SF != block1->SoH_SF) return false;
8295+
if (block0->V_SF != block1->V_SF) return false;
8296+
if (block0->CellV_SF != block1->CellV_SF) return false;
8297+
if (block0->A_SF != block1->A_SF) return false;
8298+
if (block0->AMax_SF != block1->AMax_SF) return false;
8299+
if (block0->W_SF != block1->W_SF) return false;
8300+
return true;
8301+
}
8302+
8303+
static const MetersSunSpecParser::ModelData model_802_data = {
8304+
802, // model_id
8305+
62, // model_length
8306+
64, // interesting_registers_count
8307+
false, // is_meter
8308+
true, // read_twice
8309+
&model_802_validator,
8310+
4, // value_count
8311+
{ // value_data
8312+
{ &get_model_802_SoC, MeterValueID::StateOfCharge, 56 },
8313+
{ &get_model_802_V, MeterValueID::VoltageDC, 59 },
8314+
{ &get_model_802_A, MeterValueID::CurrentDCChaDisDiff, 61 },
8315+
{ &get_model_802_W, MeterValueID::PowerDCChaDisDiff, 63 },
8316+
}
8317+
};
8318+
82348319

82358320
const MetersSunSpecParser::AllModelData meters_sun_spec_all_model_data {
8236-
18, // model_count
8321+
19, // model_count
82378322
{ // model_data
82388323
&model_001_data,
82398324
&model_101_data,
@@ -8253,5 +8338,6 @@ const MetersSunSpecParser::AllModelData meters_sun_spec_all_model_data {
82538338
&model_701_data,
82548339
&model_713_data,
82558340
&model_714_data,
8341+
&model_802_data,
82568342
}
82578343
};

software/src/modules/meters_sun_spec/prepare.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
ModelSpec('DER DC Measurements', 'DC Measurements', 'DC-Messwerte', 714, True, 'Unknown', True),
9999
ModelSpec('DER Control', 'FIXME', 'FIXME', 715, False, 'Unknown', False),
100100
ModelSpec('Battery Base Deprecated', 'FIXME', 'FIXME', 801, False, 'Battery', False),
101-
ModelSpec('Battery Base', 'Battery', 'Batterie', 802, True, 'Battery', False),
101+
ModelSpec('Battery Base', 'Battery', 'Batterie', 802, True, 'Battery', True),
102102
ModelSpec('Battery Lithium-Ion', 'FIXME', 'FIXME', 803, False, 'Battery', False),
103103
ModelSpec('Battery Lithium-Ion String', 'FIXME', 'FIXME', 804, False, 'Battery', False),
104104
ModelSpec('Battery Lithium-Ion Module', 'FIXME', 'FIXME', 805, False, 'Battery', False),

0 commit comments

Comments
 (0)