Skip to content

Commit

Permalink
meters-sun-spec: Add support for battery base model 802
Browse files Browse the repository at this point in the history
  • Loading branch information
photron committed Mar 5, 2025
1 parent 5840473 commit c3115de
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
sys.exit(1)

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

value_id_mappings_inverter = {
"A" : [ "CurrentLSumExport", None ],
Expand Down Expand Up @@ -207,6 +207,13 @@
"SoC" : [ "StateOfCharge", None ],
}

value_id_mappings_battery = {
"V" : [ "VoltageDC", None ],
"A" : [ "CurrentDCChaDisDiff", None ],
"W" : [ "PowerDCChaDisDiff", None ],
"SoC" : [ "StateOfCharge", None ],
}

# Unmapped SunSpec IDs
# "ID" : None,
# "L" : None,
Expand Down Expand Up @@ -287,6 +294,8 @@
value_id_mappings = value_id_mappings_meter
elif model_id >= 700 and model_id <= 799:
value_id_mappings = value_id_mappings_der
elif model_id >= 800 and model_id <= 899:
value_id_mappings = value_id_mappings_battery
else:
print(f"No value ID mappings available for model ID {model_id}.", file=sys.stderr)
exit(1)
Expand Down
98 changes: 98 additions & 0 deletions software/src/modules/meters_sun_spec/models/model_802.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// WARNING: This file is generated.

#pragma once

#include <stdint.h>
#include <stdlib.h>

#if defined(__GNUC__)
#pragma GCC diagnostic push
#include "gcc_warnings.h"
#pragma GCC diagnostic ignored "-Wattributes"
#endif

// ========================
// 802 - Battery Base Model
// ========================

struct SunSpecBatteryBaseModelModel802_s {
uint16_t ID; // 0
uint16_t L; // 1
uint16_t AHRtg; // 2
uint16_t WHRtg; // 3
uint16_t WChaRteMax; // 4
uint16_t WDisChaRteMax; // 5
uint16_t DisChaRte; // 6
uint16_t SoCMax; // 7
uint16_t SoCMin; // 8
uint16_t SocRsvMax; // 9
uint16_t SoCRsvMin; // 10
uint16_t SoC; // 11
uint16_t DoD; // 12
uint16_t SoH; // 13
[[gnu::packed]] uint32_t NCyc; // 14
uint16_t ChaSt; // 16
uint16_t LocRemCtl; // 17
uint16_t Hb; // 18
uint16_t CtrlHb; // 19
uint16_t AlmRst; // 20
uint16_t Typ; // 21
uint16_t State; // 22
uint16_t StateVnd; // 23
[[gnu::packed]] uint32_t WarrDt; // 24
[[gnu::packed]] uint32_t Evt1; // 26
[[gnu::packed]] uint32_t Evt2; // 28
[[gnu::packed]] uint32_t EvtVnd1; // 30
[[gnu::packed]] uint32_t EvtVnd2; // 32
uint16_t V; // 34
uint16_t VMax; // 35
uint16_t VMin; // 36
uint16_t CellVMax; // 37
uint16_t CellVMaxStr; // 38
uint16_t CellVMaxMod; // 39
uint16_t CellVMin; // 40
uint16_t CellVMinStr; // 41
uint16_t CellVMinMod; // 42
uint16_t CellVAvg; // 43
int16_t A; // 44
uint16_t AChaMax; // 45
uint16_t ADisChaMax; // 46
int16_t W; // 47
uint16_t ReqInvState; // 48
int16_t ReqW; // 49
uint16_t SetOp; // 50
uint16_t SetInvState; // 51
int16_t AHRtg_SF; // 52
int16_t WHRtg_SF; // 53
int16_t WChaDisChaMax_SF; // 54
int16_t DisChaRte_SF; // 55
int16_t SoC_SF; // 56
int16_t DoD_SF; // 57
int16_t SoH_SF; // 58
int16_t V_SF; // 59
int16_t CellV_SF; // 60
int16_t A_SF; // 61
int16_t AMax_SF; // 62
int16_t W_SF; // 63
};

#define SUNSPEC_MODEL_802_NAME "Battery Base Model"

// Total size in bytes, includes ID and length registers.
#define SUNSPEC_MODEL_802_SIZE (128)

// Register count without ID and length registers, should match content of length register.
#define SUNSPEC_MODEL_802_LENGTH (62)

union SunSpecBatteryBaseModelModel802_u {
struct SunSpecBatteryBaseModelModel802_s model;
uint16_t registers[SUNSPEC_MODEL_802_SIZE / sizeof(uint16_t)];
};

static_assert(sizeof(SunSpecBatteryBaseModelModel802_s) == 128, "Incorrect Battery Base Model length.");
static_assert(sizeof(SunSpecBatteryBaseModelModel802_u) == 128, "Incorrect Battery Base Model length.");
static_assert(sizeof(static_cast<SunSpecBatteryBaseModelModel802_u *>(nullptr)->registers) == 128, "Incorrect Battery Base Model length.");

#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
88 changes: 87 additions & 1 deletion software/src/modules/meters_sun_spec/models/model_parser_gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8231,9 +8231,94 @@ static const MetersSunSpecParser::ModelData model_714_data = {
}
};

// ========================
// 802 - Battery Base Model
// ========================

#include "model_802.h"

static float get_model_802_SoC(const void *register_data, uint32_t quirks, bool detection)
{
const struct SunSpecBatteryBaseModelModel802_s *model = static_cast<const struct SunSpecBatteryBaseModelModel802_s *>(register_data);
uint16_t val = model->SoC;
if (val == UINT16_MAX) return NAN;
float fval = static_cast<float>(val);
fval *= get_sun_spec_scale_factor(model->SoC_SF);
return fval;
}

static float get_model_802_V(const void *register_data, uint32_t quirks, bool detection)
{
const struct SunSpecBatteryBaseModelModel802_s *model = static_cast<const struct SunSpecBatteryBaseModelModel802_s *>(register_data);
uint16_t val = model->V;
if (val == UINT16_MAX) return NAN;
float fval = static_cast<float>(val);
fval *= get_sun_spec_scale_factor(model->V_SF);
return fval;
}

static float get_model_802_A(const void *register_data, uint32_t quirks, bool detection)
{
const struct SunSpecBatteryBaseModelModel802_s *model = static_cast<const struct SunSpecBatteryBaseModelModel802_s *>(register_data);
int16_t val = model->A;
if (val == INT16_MIN) return NAN;
float fval = static_cast<float>(val);
fval *= get_sun_spec_scale_factor(model->A_SF);
return fval;
}

static float get_model_802_W(const void *register_data, uint32_t quirks, bool detection)
{
const struct SunSpecBatteryBaseModelModel802_s *model = static_cast<const struct SunSpecBatteryBaseModelModel802_s *>(register_data);
int16_t val = model->W;
if (val == INT16_MIN) return NAN;
float fval = static_cast<float>(val);
fval *= get_sun_spec_scale_factor(model->W_SF);
return fval;
}

static bool model_802_validator(const uint16_t * const register_data[2])
{
const SunSpecBatteryBaseModelModel802_s *block0 = reinterpret_cast<const SunSpecBatteryBaseModelModel802_s *>(register_data[0]);
const SunSpecBatteryBaseModelModel802_s *block1 = reinterpret_cast<const SunSpecBatteryBaseModelModel802_s *>(register_data[1]);
if (block0->ID != 802) return false;
if (block1->ID != 802) return false;
if (block0->L != 62) return false;
if (block1->L != 62) return false;
if (block0->AHRtg_SF != block1->AHRtg_SF) return false;
if (block0->WHRtg_SF != block1->WHRtg_SF) return false;
if (block0->WChaDisChaMax_SF != block1->WChaDisChaMax_SF) return false;
if (block0->DisChaRte_SF != block1->DisChaRte_SF) return false;
if (block0->SoC_SF != block1->SoC_SF) return false;
if (block0->DoD_SF != block1->DoD_SF) return false;
if (block0->SoH_SF != block1->SoH_SF) return false;
if (block0->V_SF != block1->V_SF) return false;
if (block0->CellV_SF != block1->CellV_SF) return false;
if (block0->A_SF != block1->A_SF) return false;
if (block0->AMax_SF != block1->AMax_SF) return false;
if (block0->W_SF != block1->W_SF) return false;
return true;
}

static const MetersSunSpecParser::ModelData model_802_data = {
802, // model_id
62, // model_length
64, // interesting_registers_count
false, // is_meter
true, // read_twice
&model_802_validator,
4, // value_count
{ // value_data
{ &get_model_802_SoC, MeterValueID::StateOfCharge, 56 },
{ &get_model_802_V, MeterValueID::VoltageDC, 59 },
{ &get_model_802_A, MeterValueID::CurrentDCChaDisDiff, 61 },
{ &get_model_802_W, MeterValueID::PowerDCChaDisDiff, 63 },
}
};


const MetersSunSpecParser::AllModelData meters_sun_spec_all_model_data {
18, // model_count
19, // model_count
{ // model_data
&model_001_data,
&model_101_data,
Expand All @@ -8253,5 +8338,6 @@ const MetersSunSpecParser::AllModelData meters_sun_spec_all_model_data {
&model_701_data,
&model_713_data,
&model_714_data,
&model_802_data,
}
};
2 changes: 1 addition & 1 deletion software/src/modules/meters_sun_spec/prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
ModelSpec('DER DC Measurements', 'DC Measurements', 'DC-Messwerte', 714, True, 'Unknown', True),
ModelSpec('DER Control', 'FIXME', 'FIXME', 715, False, 'Unknown', False),
ModelSpec('Battery Base Deprecated', 'FIXME', 'FIXME', 801, False, 'Battery', False),
ModelSpec('Battery Base', 'Battery', 'Batterie', 802, True, 'Battery', False),
ModelSpec('Battery Base', 'Battery', 'Batterie', 802, True, 'Battery', True),
ModelSpec('Battery Lithium-Ion', 'FIXME', 'FIXME', 803, False, 'Battery', False),
ModelSpec('Battery Lithium-Ion String', 'FIXME', 'FIXME', 804, False, 'Battery', False),
ModelSpec('Battery Lithium-Ion Module', 'FIXME', 'FIXME', 805, False, 'Battery', False),
Expand Down

0 comments on commit c3115de

Please sign in to comment.