Skip to content

Commit

Permalink
use frozen::string and frozen::map where reasonable (#593)
Browse files Browse the repository at this point in the history
this change utilizes some of the features from library "frozen", which
was included upstream for the grid profile parser. to improve code
maintainability, a couple of std::maps mapping strings to values or the
other way around were introduced in OpenDTU-OnBattery-specific code at
the expense of some flash and computing overhead.

library "frozen" offers constexpr versions of map and string, which
saves initialization code and offers slightly faster lookups. this
brings the binary size down by ~25kB and should provide a small
performance improvement at runtime.
  • Loading branch information
schlimmchen authored Jan 4, 2024
1 parent e9def28 commit 3c8b8d4
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 176 deletions.
3 changes: 2 additions & 1 deletion include/JkBmsController.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <memory>
#include <vector>
#include <frozen/string.h>

#include "Battery.h"
#include "JkBmsSerialMessage.h"
Expand Down Expand Up @@ -30,7 +31,7 @@ class Controller : public BatteryProvider {
FrameCompleted
};

std::string const& getStatusText(Status status);
frozen::string const& getStatusText(Status status);
void announceStatus(Status status);
void sendRequest(uint8_t pollInterval);
void rxData(uint8_t inbyte);
Expand Down
6 changes: 4 additions & 2 deletions include/JkBmsDataPoints.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <string>
#include <unordered_map>
#include <variant>
#include <frozen/map.h>
#include <frozen/string.h>

namespace JkBms {

Expand Down Expand Up @@ -33,7 +35,7 @@ enum class AlarmBits : uint16_t {
#undef ALARM_ENUM
};

static const std::map<AlarmBits, std::string> AlarmBitTexts = {
static const frozen::map<AlarmBits, frozen::string, 16> AlarmBitTexts = {
#define ALARM_TEXT(name, value) { AlarmBits::name, #name },
ALARM_BITS(ALARM_TEXT)
#undef ALARM_TEXT
Expand All @@ -51,7 +53,7 @@ enum class StatusBits : uint16_t {
#undef STATUS_ENUM
};

static const std::map<StatusBits, std::string> StatusBitTexts = {
static const frozen::map<StatusBits, frozen::string, 4> StatusBitTexts = {
#define STATUS_TEXT(name, value) { StatusBits::name, #name },
STATUS_BITS(STATUS_TEXT)
#undef STATUS_TEXT
Expand Down
3 changes: 2 additions & 1 deletion include/PowerLimiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <memory>
#include <functional>
#include <TaskSchedulerDeclarations.h>
#include <frozen/string.h>

#define PL_UI_STATE_INACTIVE 0
#define PL_UI_STATE_CHARGING 1
Expand Down Expand Up @@ -83,7 +84,7 @@ class PowerLimiterClass {
bool _fullSolarPassThroughEnabled = false;
bool _verboseLogging = true;

std::string const& getStatusText(Status status);
frozen::string const& getStatusText(Status status);
void announceStatus(Status status);
bool shutdown(Status status);
bool shutdown() { return shutdown(_lastStatus); }
Expand Down
174 changes: 79 additions & 95 deletions lib/VeDirectFrameHandler/VeDirectFrameHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,106 +295,90 @@ uint32_t VeDirectFrameHandler::getLastUpdate() const
return _lastUpdate;
}

template<typename T>
String const& VeDirectFrameHandler::getAsString(std::map<T, String> const& values, T val)
{
auto pos = values.find(val);
if (pos == values.end()) {
static String dummy;
dummy = val;
return dummy;
}
return pos->second;
}

template String const& VeDirectFrameHandler::getAsString(std::map<uint8_t, String> const& values, uint8_t val);
template String const& VeDirectFrameHandler::getAsString(std::map<uint16_t, String> const& values, uint16_t val);
template String const& VeDirectFrameHandler::getAsString(std::map<uint32_t, String> const& values, uint32_t val);

/*
* getPidAsString
* This function returns the product id (PID) as readable text.
*/
String VeDirectFrameHandler::veStruct::getPidAsString() const
frozen::string const& VeDirectFrameHandler::veStruct::getPidAsString() const
{
static const std::map<uint16_t, String> values = {
{ 0x0300, F("BlueSolar MPPT 70|15") },
{ 0xA040, F("BlueSolar MPPT 75|50") },
{ 0xA041, F("BlueSolar MPPT 150|35") },
{ 0xA042, F("BlueSolar MPPT 75|15") },
{ 0xA043, F("BlueSolar MPPT 100|15") },
{ 0xA044, F("BlueSolar MPPT 100|30") },
{ 0xA045, F("BlueSolar MPPT 100|50") },
{ 0xA046, F("BlueSolar MPPT 100|70") },
{ 0xA047, F("BlueSolar MPPT 150|100") },
{ 0xA049, F("BlueSolar MPPT 100|50 rev2") },
{ 0xA04A, F("BlueSolar MPPT 100|30 rev2") },
{ 0xA04B, F("BlueSolar MPPT 150|35 rev2") },
{ 0xA04C, F("BlueSolar MPPT 75|10") },
{ 0xA04D, F("BlueSolar MPPT 150|45") },
{ 0xA04E, F("BlueSolar MPPT 150|60") },
{ 0xA04F, F("BlueSolar MPPT 150|85") },
{ 0xA050, F("SmartSolar MPPT 250|100") },
{ 0xA051, F("SmartSolar MPPT 150|100") },
{ 0xA052, F("SmartSolar MPPT 150|85") },
{ 0xA053, F("SmartSolar MPPT 75|15") },
{ 0xA054, F("SmartSolar MPPT 75|10") },
{ 0xA055, F("SmartSolar MPPT 100|15") },
{ 0xA056, F("SmartSolar MPPT 100|30") },
{ 0xA057, F("SmartSolar MPPT 100|50") },
{ 0xA058, F("SmartSolar MPPT 150|35") },
{ 0xA059, F("SmartSolar MPPT 150|10 rev2") },
{ 0xA05A, F("SmartSolar MPPT 150|85 rev2") },
{ 0xA05B, F("SmartSolar MPPT 250|70") },
{ 0xA05C, F("SmartSolar MPPT 250|85") },
{ 0xA05D, F("SmartSolar MPPT 250|60") },
{ 0xA05E, F("SmartSolar MPPT 250|45") },
{ 0xA05F, F("SmartSolar MPPT 100|20") },
{ 0xA060, F("SmartSolar MPPT 100|20 48V") },
{ 0xA061, F("SmartSolar MPPT 150|45") },
{ 0xA062, F("SmartSolar MPPT 150|60") },
{ 0xA063, F("SmartSolar MPPT 150|70") },
{ 0xA064, F("SmartSolar MPPT 250|85 rev2") },
{ 0xA065, F("SmartSolar MPPT 250|100 rev2") },
{ 0xA066, F("BlueSolar MPPT 100|20") },
{ 0xA067, F("BlueSolar MPPT 100|20 48V") },
{ 0xA068, F("SmartSolar MPPT 250|60 rev2") },
{ 0xA069, F("SmartSolar MPPT 250|70 rev2") },
{ 0xA06A, F("SmartSolar MPPT 150|45 rev2") },
{ 0xA06B, F("SmartSolar MPPT 150|60 rev2") },
{ 0xA06C, F("SmartSolar MPPT 150|70 rev2") },
{ 0xA06D, F("SmartSolar MPPT 150|85 rev3") },
{ 0xA06E, F("SmartSolar MPPT 150|100 rev3") },
{ 0xA06F, F("BlueSolar MPPT 150|45 rev2") },
{ 0xA070, F("BlueSolar MPPT 150|60 rev2") },
{ 0xA071, F("BlueSolar MPPT 150|70 rev2") },
{ 0xA102, F("SmartSolar MPPT VE.Can 150|70") },
{ 0xA103, F("SmartSolar MPPT VE.Can 150|45") },
{ 0xA104, F("SmartSolar MPPT VE.Can 150|60") },
{ 0xA105, F("SmartSolar MPPT VE.Can 150|85") },
{ 0xA106, F("SmartSolar MPPT VE.Can 150|100") },
{ 0xA107, F("SmartSolar MPPT VE.Can 250|45") },
{ 0xA108, F("SmartSolar MPPT VE.Can 250|60") },
{ 0xA109, F("SmartSolar MPPT VE.Can 250|80") },
{ 0xA10A, F("SmartSolar MPPT VE.Can 250|85") },
{ 0xA10B, F("SmartSolar MPPT VE.Can 250|100") },
{ 0xA10C, F("SmartSolar MPPT VE.Can 150|70 rev2") },
{ 0xA10D, F("SmartSolar MPPT VE.Can 150|85 rev2") },
{ 0xA10E, F("SmartSolar MPPT VE.Can 150|100 rev2") },
{ 0xA10F, F("BlueSolar MPPT VE.Can 150|100") },
{ 0xA110, F("SmartSolar MPPT RS 450|100") },
{ 0xA112, F("BlueSolar MPPT VE.Can 250|70") },
{ 0xA113, F("BlueSolar MPPT VE.Can 250|100") },
{ 0xA114, F("SmartSolar MPPT VE.Can 250|70 rev2") },
{ 0xA115, F("SmartSolar MPPT VE.Can 250|100 rev2") },
{ 0xA116, F("SmartSolar MPPT VE.Can 250|85 rev2") },
{ 0xA381, F("BMV-712 Smart") },
{ 0xA382, F("BMV-710H Smart") },
{ 0xA383, F("BMV-712 Smart Rev2") },
{ 0xA389, F("SmartShunt 500A/50mV") },
{ 0xA38A, F("SmartShunt 1000A/50mV") },
{ 0xA38B, F("SmartShunt 2000A/50mV") },
{ 0xA3F0, F("SmartShunt 2000A/50mV" ) }
static constexpr frozen::map<uint16_t, frozen::string, 77> values = {
{ 0x0300, "BlueSolar MPPT 70|15" },
{ 0xA040, "BlueSolar MPPT 75|50" },
{ 0xA041, "BlueSolar MPPT 150|35" },
{ 0xA042, "BlueSolar MPPT 75|15" },
{ 0xA043, "BlueSolar MPPT 100|15" },
{ 0xA044, "BlueSolar MPPT 100|30" },
{ 0xA045, "BlueSolar MPPT 100|50" },
{ 0xA046, "BlueSolar MPPT 100|70" },
{ 0xA047, "BlueSolar MPPT 150|100" },
{ 0xA049, "BlueSolar MPPT 100|50 rev2" },
{ 0xA04A, "BlueSolar MPPT 100|30 rev2" },
{ 0xA04B, "BlueSolar MPPT 150|35 rev2" },
{ 0xA04C, "BlueSolar MPPT 75|10" },
{ 0xA04D, "BlueSolar MPPT 150|45" },
{ 0xA04E, "BlueSolar MPPT 150|60" },
{ 0xA04F, "BlueSolar MPPT 150|85" },
{ 0xA050, "SmartSolar MPPT 250|100" },
{ 0xA051, "SmartSolar MPPT 150|100" },
{ 0xA052, "SmartSolar MPPT 150|85" },
{ 0xA053, "SmartSolar MPPT 75|15" },
{ 0xA054, "SmartSolar MPPT 75|10" },
{ 0xA055, "SmartSolar MPPT 100|15" },
{ 0xA056, "SmartSolar MPPT 100|30" },
{ 0xA057, "SmartSolar MPPT 100|50" },
{ 0xA058, "SmartSolar MPPT 150|35" },
{ 0xA059, "SmartSolar MPPT 150|10 rev2" },
{ 0xA05A, "SmartSolar MPPT 150|85 rev2" },
{ 0xA05B, "SmartSolar MPPT 250|70" },
{ 0xA05C, "SmartSolar MPPT 250|85" },
{ 0xA05D, "SmartSolar MPPT 250|60" },
{ 0xA05E, "SmartSolar MPPT 250|45" },
{ 0xA05F, "SmartSolar MPPT 100|20" },
{ 0xA060, "SmartSolar MPPT 100|20 48V" },
{ 0xA061, "SmartSolar MPPT 150|45" },
{ 0xA062, "SmartSolar MPPT 150|60" },
{ 0xA063, "SmartSolar MPPT 150|70" },
{ 0xA064, "SmartSolar MPPT 250|85 rev2" },
{ 0xA065, "SmartSolar MPPT 250|100 rev2" },
{ 0xA066, "BlueSolar MPPT 100|20" },
{ 0xA067, "BlueSolar MPPT 100|20 48V" },
{ 0xA068, "SmartSolar MPPT 250|60 rev2" },
{ 0xA069, "SmartSolar MPPT 250|70 rev2" },
{ 0xA06A, "SmartSolar MPPT 150|45 rev2" },
{ 0xA06B, "SmartSolar MPPT 150|60 rev2" },
{ 0xA06C, "SmartSolar MPPT 150|70 rev2" },
{ 0xA06D, "SmartSolar MPPT 150|85 rev3" },
{ 0xA06E, "SmartSolar MPPT 150|100 rev3" },
{ 0xA06F, "BlueSolar MPPT 150|45 rev2" },
{ 0xA070, "BlueSolar MPPT 150|60 rev2" },
{ 0xA071, "BlueSolar MPPT 150|70 rev2" },
{ 0xA102, "SmartSolar MPPT VE.Can 150|70" },
{ 0xA103, "SmartSolar MPPT VE.Can 150|45" },
{ 0xA104, "SmartSolar MPPT VE.Can 150|60" },
{ 0xA105, "SmartSolar MPPT VE.Can 150|85" },
{ 0xA106, "SmartSolar MPPT VE.Can 150|100" },
{ 0xA107, "SmartSolar MPPT VE.Can 250|45" },
{ 0xA108, "SmartSolar MPPT VE.Can 250|60" },
{ 0xA109, "SmartSolar MPPT VE.Can 250|80" },
{ 0xA10A, "SmartSolar MPPT VE.Can 250|85" },
{ 0xA10B, "SmartSolar MPPT VE.Can 250|100" },
{ 0xA10C, "SmartSolar MPPT VE.Can 150|70 rev2" },
{ 0xA10D, "SmartSolar MPPT VE.Can 150|85 rev2" },
{ 0xA10E, "SmartSolar MPPT VE.Can 150|100 rev2" },
{ 0xA10F, "BlueSolar MPPT VE.Can 150|100" },
{ 0xA110, "SmartSolar MPPT RS 450|100" },
{ 0xA112, "BlueSolar MPPT VE.Can 250|70" },
{ 0xA113, "BlueSolar MPPT VE.Can 250|100" },
{ 0xA114, "SmartSolar MPPT VE.Can 250|70 rev2" },
{ 0xA115, "SmartSolar MPPT VE.Can 250|100 rev2" },
{ 0xA116, "SmartSolar MPPT VE.Can 250|85 rev2" },
{ 0xA381, "BMV-712 Smart" },
{ 0xA382, "BMV-710H Smart" },
{ 0xA383, "BMV-712 Smart Rev2" },
{ 0xA389, "SmartShunt 500A/50mV" },
{ 0xA38A, "SmartShunt 1000A/50mV" },
{ 0xA38B, "SmartShunt 2000A/50mV" },
{ 0xA3F0, "SmartShunt 2000A/50mV" }
};

return getAsString(values, PID);
Expand Down
17 changes: 13 additions & 4 deletions lib/VeDirectFrameHandler/VeDirectFrameHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@

#include <Arduino.h>
#include <array>
#include <map>
#include <frozen/string.h>
#include <frozen/map.h>
#include <memory>

#define VE_MAX_VALUE_LEN 33 // VE.Direct Protocol: max value size is 33 including /0
Expand All @@ -39,14 +40,22 @@ class VeDirectFrameHandler {
double I = 0; // battery current in A
double E = 0; // efficiency in percent (calculated, moving average)

String getPidAsString() const; // product id as string
frozen::string const& getPidAsString() const; // product ID as string
} veStruct;

bool textRxEvent(std::string const& who, char* name, char* value, veStruct& frame);
bool isDataValid(veStruct const& frame) const; // return true if data valid and not outdated

template<typename T>
static String const& getAsString(std::map<T, String> const& values, T val);
template<typename T, size_t L>
static frozen::string const& getAsString(frozen::map<T, frozen::string, L> const& values, T val)
{
auto pos = values.find(val);
if (pos == values.end()) {
static constexpr frozen::string dummy("???");
return dummy;
}
return pos->second;
}

private:
void setLastUpdate(); // set timestampt after successful frame read
Expand Down
Loading

0 comments on commit 3c8b8d4

Please sign in to comment.