use frozen::string and frozen::map where reasonable (#593)

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.
This commit is contained in:
Bernhard Kirchen 2024-01-04 23:28:34 +01:00 committed by GitHub
parent e9def28f3e
commit 3c8b8d4427
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 172 additions and 176 deletions

View File

@ -2,6 +2,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <frozen/string.h>
#include "Battery.h" #include "Battery.h"
#include "JkBmsSerialMessage.h" #include "JkBmsSerialMessage.h"
@ -30,7 +31,7 @@ class Controller : public BatteryProvider {
FrameCompleted FrameCompleted
}; };
std::string const& getStatusText(Status status); frozen::string const& getStatusText(Status status);
void announceStatus(Status status); void announceStatus(Status status);
void sendRequest(uint8_t pollInterval); void sendRequest(uint8_t pollInterval);
void rxData(uint8_t inbyte); void rxData(uint8_t inbyte);

View File

@ -6,6 +6,8 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <variant> #include <variant>
#include <frozen/map.h>
#include <frozen/string.h>
namespace JkBms { namespace JkBms {
@ -33,7 +35,7 @@ enum class AlarmBits : uint16_t {
#undef ALARM_ENUM #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 }, #define ALARM_TEXT(name, value) { AlarmBits::name, #name },
ALARM_BITS(ALARM_TEXT) ALARM_BITS(ALARM_TEXT)
#undef ALARM_TEXT #undef ALARM_TEXT
@ -51,7 +53,7 @@ enum class StatusBits : uint16_t {
#undef STATUS_ENUM #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 }, #define STATUS_TEXT(name, value) { StatusBits::name, #name },
STATUS_BITS(STATUS_TEXT) STATUS_BITS(STATUS_TEXT)
#undef STATUS_TEXT #undef STATUS_TEXT

View File

@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include <functional> #include <functional>
#include <TaskSchedulerDeclarations.h> #include <TaskSchedulerDeclarations.h>
#include <frozen/string.h>
#define PL_UI_STATE_INACTIVE 0 #define PL_UI_STATE_INACTIVE 0
#define PL_UI_STATE_CHARGING 1 #define PL_UI_STATE_CHARGING 1
@ -83,7 +84,7 @@ private:
bool _fullSolarPassThroughEnabled = false; bool _fullSolarPassThroughEnabled = false;
bool _verboseLogging = true; bool _verboseLogging = true;
std::string const& getStatusText(Status status); frozen::string const& getStatusText(Status status);
void announceStatus(Status status); void announceStatus(Status status);
bool shutdown(Status status); bool shutdown(Status status);
bool shutdown() { return shutdown(_lastStatus); } bool shutdown() { return shutdown(_lastStatus); }

View File

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

View File

@ -13,7 +13,8 @@
#include <Arduino.h> #include <Arduino.h>
#include <array> #include <array>
#include <map> #include <frozen/string.h>
#include <frozen/map.h>
#include <memory> #include <memory>
#define VE_MAX_VALUE_LEN 33 // VE.Direct Protocol: max value size is 33 including /0 #define VE_MAX_VALUE_LEN 33 // VE.Direct Protocol: max value size is 33 including /0
@ -39,14 +40,22 @@ protected:
double I = 0; // battery current in A double I = 0; // battery current in A
double E = 0; // efficiency in percent (calculated, moving average) 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; } veStruct;
bool textRxEvent(std::string const& who, char* name, char* value, veStruct& frame); 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 bool isDataValid(veStruct const& frame) const; // return true if data valid and not outdated
template<typename T> template<typename T, size_t L>
static String const& getAsString(std::map<T, String> const& values, T val); 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: private:
void setLastUpdate(); // set timestampt after successful frame read void setLastUpdate(); // set timestampt after successful frame read

View File

@ -1,5 +1,4 @@
#include <Arduino.h> #include <Arduino.h>
#include <map>
#include "VeDirectMpptController.h" #include "VeDirectMpptController.h"
void VeDirectMpptController::init(int8_t rx, int8_t tx, Print* msgOut, bool verboseLogging) void VeDirectMpptController::init(int8_t rx, int8_t tx, Print* msgOut, bool verboseLogging)
@ -90,18 +89,18 @@ void VeDirectMpptController::frameValidEvent() {
* getCsAsString * getCsAsString
* This function returns the state of operations (CS) as readable text. * This function returns the state of operations (CS) as readable text.
*/ */
String VeDirectMpptController::veMpptStruct::getCsAsString() const frozen::string const& VeDirectMpptController::veMpptStruct::getCsAsString() const
{ {
static const std::map<uint8_t, String> values = { static constexpr frozen::map<uint8_t, frozen::string, 9> values = {
{ 0, F("OFF") }, { 0, "OFF" },
{ 2, F("Fault") }, { 2, "Fault" },
{ 3, F("Bulk") }, { 3, "Bulk" },
{ 4, F("Absorbtion") }, { 4, "Absorbtion" },
{ 5, F("Float") }, { 5, "Float" },
{ 7, F("Equalize (manual)") }, { 7, "Equalize (manual)" },
{ 245, F("Starting-up") }, { 245, "Starting-up" },
{ 247, F("Auto equalize / Recondition") }, { 247, "Auto equalize / Recondition" },
{ 252, F("External Control") } { 252, "External Control" }
}; };
return getAsString(values, CS); return getAsString(values, CS);
@ -111,12 +110,12 @@ String VeDirectMpptController::veMpptStruct::getCsAsString() const
* getMpptAsString * getMpptAsString
* This function returns the state of MPPT (MPPT) as readable text. * This function returns the state of MPPT (MPPT) as readable text.
*/ */
String VeDirectMpptController::veMpptStruct::getMpptAsString() const frozen::string const& VeDirectMpptController::veMpptStruct::getMpptAsString() const
{ {
static const std::map<uint8_t, String> values = { static constexpr frozen::map<uint8_t, frozen::string, 3> values = {
{ 0, F("OFF") }, { 0, "OFF" },
{ 1, F("Voltage or current limited") }, { 1, "Voltage or current limited" },
{ 2, F("MPP Tracker active") } { 2, "MPP Tracker active" }
}; };
return getAsString(values, MPPT); return getAsString(values, MPPT);
@ -126,29 +125,29 @@ String VeDirectMpptController::veMpptStruct::getMpptAsString() const
* getErrAsString * getErrAsString
* This function returns error state (ERR) as readable text. * This function returns error state (ERR) as readable text.
*/ */
String VeDirectMpptController::veMpptStruct::getErrAsString() const frozen::string const& VeDirectMpptController::veMpptStruct::getErrAsString() const
{ {
static const std::map<uint8_t, String> values = { static constexpr frozen::map<uint8_t, frozen::string, 20> values = {
{ 0, F("No error") }, { 0, "No error" },
{ 2, F("Battery voltage too high") }, { 2, "Battery voltage too high" },
{ 17, F("Charger temperature too high") }, { 17, "Charger temperature too high" },
{ 18, F("Charger over current") }, { 18, "Charger over current" },
{ 19, F("Charger current reversed") }, { 19, "Charger current reversed" },
{ 20, F("Bulk time limit exceeded") }, { 20, "Bulk time limit exceeded" },
{ 21, F("Current sensor issue(sensor bias/sensor broken)") }, { 21, "Current sensor issue(sensor bias/sensor broken)" },
{ 26, F("Terminals overheated") }, { 26, "Terminals overheated" },
{ 28, F("Converter issue (dual converter models only)") }, { 28, "Converter issue (dual converter models only)" },
{ 33, F("Input voltage too high (solar panel)") }, { 33, "Input voltage too high (solar panel)" },
{ 34, F("Input current too high (solar panel)") }, { 34, "Input current too high (solar panel)" },
{ 38, F("Input shutdown (due to excessive battery voltage)") }, { 38, "Input shutdown (due to excessive battery voltage)" },
{ 39, F("Input shutdown (due to current flow during off mode)") }, { 39, "Input shutdown (due to current flow during off mode)" },
{ 40, F("Input") }, { 40, "Input" },
{ 65, F("Lost communication with one of devices") }, { 65, "Lost communication with one of devices" },
{ 67, F("Synchronisedcharging device configuration issue") }, { 67, "Synchronisedcharging device configuration issue" },
{ 68, F("BMS connection lost") }, { 68, "BMS connection lost" },
{ 116, F("Factory calibration data lost") }, { 116, "Factory calibration data lost" },
{ 117, F("Invalid/incompatible firmware") }, { 117, "Invalid/incompatible firmware" },
{ 118, F("User settings invalid") } { 118, "User settings invalid" }
}; };
return getAsString(values, ERR); return getAsString(values, ERR);
@ -158,19 +157,19 @@ String VeDirectMpptController::veMpptStruct::getErrAsString() const
* getOrAsString * getOrAsString
* This function returns the off reason (OR) as readable text. * This function returns the off reason (OR) as readable text.
*/ */
String VeDirectMpptController::veMpptStruct::getOrAsString() const frozen::string const& VeDirectMpptController::veMpptStruct::getOrAsString() const
{ {
static const std::map<uint32_t, String> values = { static constexpr frozen::map<uint32_t, frozen::string, 10> values = {
{ 0x00000000, F("Not off") }, { 0x00000000, "Not off" },
{ 0x00000001, F("No input power") }, { 0x00000001, "No input power" },
{ 0x00000002, F("Switched off (power switch)") }, { 0x00000002, "Switched off (power switch)" },
{ 0x00000004, F("Switched off (device moderegister)") }, { 0x00000004, "Switched off (device moderegister)" },
{ 0x00000008, F("Remote input") }, { 0x00000008, "Remote input" },
{ 0x00000010, F("Protection active") }, { 0x00000010, "Protection active" },
{ 0x00000020, F("Paygo") }, { 0x00000020, "Paygo" },
{ 0x00000040, F("BMS") }, { 0x00000040, "BMS" },
{ 0x00000080, F("Engine shutdown detection") }, { 0x00000080, "Engine shutdown detection" },
{ 0x00000100, F("Analysing input voltage") } { 0x00000100, "Analysing input voltage" }
}; };
return getAsString(values, OR); return getAsString(values, OR);

View File

@ -59,10 +59,10 @@ public:
double H22; // yield yesterday kWh double H22; // yield yesterday kWh
int32_t H23; // maximum power yesterday W int32_t H23; // maximum power yesterday W
String getMpptAsString() const; // state of mppt as string frozen::string const& getMpptAsString() const; // state of mppt as string
String getCsAsString() const; // current state as string frozen::string const& getCsAsString() const; // current state as string
String getErrAsString() const; // error state as string frozen::string const& getErrAsString() const; // error state as string
String getOrAsString() const; // off reason as string frozen::string const& getOrAsString() const; // off reason as string
}; };
using spData_t = std::shared_ptr<veMpptStruct const>; using spData_t = std::shared_ptr<veMpptStruct const>;

View File

@ -277,7 +277,7 @@ void JkBmsBatteryStats::mqttPublish() const
for (auto iter = JkBms::AlarmBitTexts.begin(); iter != JkBms::AlarmBitTexts.end(); ++iter) { for (auto iter = JkBms::AlarmBitTexts.begin(); iter != JkBms::AlarmBitTexts.end(); ++iter) {
auto bit = iter->first; auto bit = iter->first;
String value = (*oAlarms & static_cast<uint16_t>(bit))?"1":"0"; String value = (*oAlarms & static_cast<uint16_t>(bit))?"1":"0";
MqttSettings.publish(String("battery/alarms/") + iter->second.c_str(), value); MqttSettings.publish(String("battery/alarms/") + iter->second.data(), value);
} }
} }
@ -286,7 +286,7 @@ void JkBmsBatteryStats::mqttPublish() const
for (auto iter = JkBms::StatusBitTexts.begin(); iter != JkBms::StatusBitTexts.end(); ++iter) { for (auto iter = JkBms::StatusBitTexts.begin(); iter != JkBms::StatusBitTexts.end(); ++iter) {
auto bit = iter->first; auto bit = iter->first;
String value = (*oStatus & static_cast<uint16_t>(bit))?"1":"0"; String value = (*oStatus & static_cast<uint16_t>(bit))?"1":"0";
MqttSettings.publish(String("battery/status/") + iter->second.c_str(), value); MqttSettings.publish(String("battery/status/") + iter->second.data(), value);
} }
} }
@ -338,7 +338,7 @@ void VictronSmartShuntStats::updateFrom(VeDirectShuntController::veShuntStruct c
_SoC = shuntData.SOC / 10; _SoC = shuntData.SOC / 10;
_voltage = shuntData.V; _voltage = shuntData.V;
_current = shuntData.I; _current = shuntData.I;
_modelName = shuntData.getPidAsString(); _modelName = shuntData.getPidAsString().data();
_chargeCycles = shuntData.H4; _chargeCycles = shuntData.H4;
_timeToGo = shuntData.TTG / 60; _timeToGo = shuntData.TTG / 60;
_chargedEnergy = shuntData.H18 / 100; _chargedEnergy = shuntData.H18 / 100;

View File

@ -5,7 +5,7 @@
#include "MessageOutput.h" #include "MessageOutput.h"
#include "JkBmsDataPoints.h" #include "JkBmsDataPoints.h"
#include "JkBmsController.h" #include "JkBmsController.h"
#include <map> #include <frozen/map.h>
//#define JKBMS_DUMMY_SERIAL //#define JKBMS_DUMMY_SERIAL
@ -255,11 +255,11 @@ Controller::Interface Controller::getInterface() const
return Interface::Invalid; return Interface::Invalid;
} }
std::string const& Controller::getStatusText(Controller::Status status) frozen::string const& Controller::getStatusText(Controller::Status status)
{ {
static const std::string missing = "programmer error: missing status text"; static constexpr frozen::string missing = "programmer error: missing status text";
static const std::map<Status, const std::string> texts = { static constexpr frozen::map<Status, frozen::string, 6> texts = {
{ Status::Timeout, "timeout wating for response from BMS" }, { Status::Timeout, "timeout wating for response from BMS" },
{ Status::WaitingForPollInterval, "waiting for poll interval to elapse" }, { Status::WaitingForPollInterval, "waiting for poll interval to elapse" },
{ Status::HwSerialNotAvailableForWrite, "UART is not available for writing" }, { Status::HwSerialNotAvailableForWrite, "UART is not available for writing" },
@ -279,7 +279,7 @@ void Controller::announceStatus(Controller::Status status)
if (_lastStatus == status && millis() < _lastStatusPrinted + 10 * 1000) { return; } if (_lastStatus == status && millis() < _lastStatusPrinted + 10 * 1000) { return; }
MessageOutput.printf("[%11.3f] JK BMS: %s\r\n", MessageOutput.printf("[%11.3f] JK BMS: %s\r\n",
static_cast<double>(millis())/1000, getStatusText(status).c_str()); static_cast<double>(millis())/1000, getStatusText(status).data());
_lastStatus = status; _lastStatus = status;
_lastStatusPrinted = millis(); _lastStatusPrinted = millis();

View File

@ -69,7 +69,7 @@ void MqttHandleVedirectClass::loop()
topic.concat("/"); topic.concat("/");
if (_PublishFull || spMpptData->PID != _kvFrame.PID) if (_PublishFull || spMpptData->PID != _kvFrame.PID)
MqttSettings.publish(topic + "PID", spMpptData->getPidAsString()); MqttSettings.publish(topic + "PID", spMpptData->getPidAsString().data());
if (_PublishFull || strcmp(spMpptData->SER, _kvFrame.SER) != 0) if (_PublishFull || strcmp(spMpptData->SER, _kvFrame.SER) != 0)
MqttSettings.publish(topic + "SER", spMpptData->SER ); MqttSettings.publish(topic + "SER", spMpptData->SER );
if (_PublishFull || strcmp(spMpptData->FW, _kvFrame.FW) != 0) if (_PublishFull || strcmp(spMpptData->FW, _kvFrame.FW) != 0)
@ -77,13 +77,13 @@ void MqttHandleVedirectClass::loop()
if (_PublishFull || spMpptData->LOAD != _kvFrame.LOAD) if (_PublishFull || spMpptData->LOAD != _kvFrame.LOAD)
MqttSettings.publish(topic + "LOAD", spMpptData->LOAD == true ? "ON": "OFF"); MqttSettings.publish(topic + "LOAD", spMpptData->LOAD == true ? "ON": "OFF");
if (_PublishFull || spMpptData->CS != _kvFrame.CS) if (_PublishFull || spMpptData->CS != _kvFrame.CS)
MqttSettings.publish(topic + "CS", spMpptData->getCsAsString()); MqttSettings.publish(topic + "CS", spMpptData->getCsAsString().data());
if (_PublishFull || spMpptData->ERR != _kvFrame.ERR) if (_PublishFull || spMpptData->ERR != _kvFrame.ERR)
MqttSettings.publish(topic + "ERR", spMpptData->getErrAsString()); MqttSettings.publish(topic + "ERR", spMpptData->getErrAsString().data());
if (_PublishFull || spMpptData->OR != _kvFrame.OR) if (_PublishFull || spMpptData->OR != _kvFrame.OR)
MqttSettings.publish(topic + "OR", spMpptData->getOrAsString()); MqttSettings.publish(topic + "OR", spMpptData->getOrAsString().data());
if (_PublishFull || spMpptData->MPPT != _kvFrame.MPPT) if (_PublishFull || spMpptData->MPPT != _kvFrame.MPPT)
MqttSettings.publish(topic + "MPPT", spMpptData->getMpptAsString()); MqttSettings.publish(topic + "MPPT", spMpptData->getMpptAsString().data());
if (_PublishFull || spMpptData->HSDS != _kvFrame.HSDS) { if (_PublishFull || spMpptData->HSDS != _kvFrame.HSDS) {
value = spMpptData->HSDS; value = spMpptData->HSDS;
MqttSettings.publish(topic + "HSDS", value); MqttSettings.publish(topic + "HSDS", value);

View File

@ -14,7 +14,7 @@
#include "MessageOutput.h" #include "MessageOutput.h"
#include <ctime> #include <ctime>
#include <cmath> #include <cmath>
#include <map> #include <frozen/map.h>
PowerLimiterClass PowerLimiter; PowerLimiterClass PowerLimiter;
@ -26,11 +26,11 @@ void PowerLimiterClass::init(Scheduler& scheduler)
_loopTask.enable(); _loopTask.enable();
} }
std::string const& PowerLimiterClass::getStatusText(PowerLimiterClass::Status status) frozen::string const& PowerLimiterClass::getStatusText(PowerLimiterClass::Status status)
{ {
static const std::string missing = "programmer error: missing status text"; static const frozen::string missing = "programmer error: missing status text";
static const std::map<Status, const std::string> texts = { static const frozen::map<Status, frozen::string, 19> texts = {
{ Status::Initializing, "initializing (should not see me)" }, { Status::Initializing, "initializing (should not see me)" },
{ Status::DisabledByConfig, "disabled by configuration" }, { Status::DisabledByConfig, "disabled by configuration" },
{ Status::DisabledByMqtt, "disabled by MQTT" }, { Status::DisabledByMqtt, "disabled by MQTT" },
@ -70,7 +70,7 @@ void PowerLimiterClass::announceStatus(PowerLimiterClass::Status status)
if (status == Status::DisabledByConfig && _lastStatus == status) { return; } if (status == Status::DisabledByConfig && _lastStatus == status) { return; }
MessageOutput.printf("[%11.3f] DPL: %s\r\n", MessageOutput.printf("[%11.3f] DPL: %s\r\n",
static_cast<double>(millis())/1000, getStatusText(status).c_str()); static_cast<double>(millis())/1000, getStatusText(status).data());
_lastStatus = status; _lastStatus = status;
_lastStatusPrinted = millis(); _lastStatusPrinted = millis();