Added sthome canbus
This commit is contained in:
parent
03045de7c2
commit
ea865dfa94
156
cb_frame.cpp
156
cb_frame.cpp
@ -2,9 +2,21 @@
|
||||
// limit the amount of logging from this class as it can be called very frequently. Too much logging can lead to instability and no connectivity.
|
||||
namespace solar
|
||||
{
|
||||
const cb_frame emptyframe = cb_frame(); // to return a reference to when no valid frame is found
|
||||
|
||||
cb_frame::cb_frame()
|
||||
{
|
||||
this->msg_id = 0;
|
||||
this->publish = false;
|
||||
this->rtr = false;
|
||||
this->can_id = 0;
|
||||
this->frame.clear();
|
||||
// ESP_LOGI(tag("frame CTOR0").c_str(), "%-20s %s", "Created frame", this->to_string().c_str());
|
||||
}
|
||||
cb_frame::cb_frame(int msg_id, uint32_t can_id)
|
||||
{
|
||||
this->msg_id = msg_id;
|
||||
this->publish = false;
|
||||
this->rtr = false;
|
||||
this->can_id = can_id;
|
||||
this->frame.clear();
|
||||
@ -13,6 +25,7 @@ namespace solar
|
||||
cb_frame::cb_frame(int msg_id, uint32_t can_id, const byte_vector& frame, bool rtr)
|
||||
{
|
||||
this->msg_id = msg_id;
|
||||
this->publish = false;
|
||||
this->rtr = rtr;
|
||||
this->can_id = can_id;
|
||||
this->frame = frame;
|
||||
@ -21,6 +34,7 @@ namespace solar
|
||||
void cb_frame::clear()
|
||||
{
|
||||
this->msg_id = 0;
|
||||
this->publish = false;
|
||||
this->rtr = false;
|
||||
this->can_id = 0;
|
||||
this->frame.clear();
|
||||
@ -28,6 +42,7 @@ namespace solar
|
||||
void cb_frame::swap(cb_frame &s)
|
||||
{
|
||||
std::swap(this->msg_id, s.msg_id);
|
||||
std::swap(this->publish, s.publish);
|
||||
std::swap(this->rtr, s.rtr);
|
||||
std::swap(this->can_id, s.can_id);
|
||||
this->frame.swap(s.frame);
|
||||
@ -35,6 +50,34 @@ namespace solar
|
||||
bool cb_frame::is_valid() const
|
||||
{
|
||||
return this->can_id != 0;
|
||||
}
|
||||
void cb_frame::setpublish(bool do_publish) const
|
||||
{
|
||||
this->publish = do_publish;
|
||||
}
|
||||
bool cb_frame::getpublish() const
|
||||
{
|
||||
return this->publish;
|
||||
}
|
||||
bool cb_frame::send_frame(esphome::canbus::Canbus *canbus, bool extended_id, bool remote_transmission_request) const
|
||||
{
|
||||
if(canbus == nullptr) {
|
||||
ESP_LOGE(tag("cb_frame::send_data").c_str(), "CAN bus interface is null, cannot send data");
|
||||
return false;
|
||||
}
|
||||
if(!this->is_valid()) {
|
||||
ESP_LOGE(tag("cb_frame::send_data").c_str(), "Frame is not valid, cannot send data: %s", this->to_string().c_str());
|
||||
return false;
|
||||
}
|
||||
return cb_frame::send_frame(canbus, this->can_id, this->frame, extended_id, remote_transmission_request);
|
||||
}
|
||||
bool cb_frame::send_frame(esphome::canbus::Canbus *canbus, uint32_t can_id, const byte_vector& frame, bool extended_id, bool remote_transmission_request)
|
||||
{
|
||||
if(canbus == nullptr) {
|
||||
return false;
|
||||
}
|
||||
canbus->send_data(can_id, extended_id, remote_transmission_request, frame);
|
||||
return true;
|
||||
}
|
||||
int cb_frame::compare(const cb_frame& b, const int *comparecolumns) const
|
||||
{
|
||||
@ -132,13 +175,13 @@ namespace solar
|
||||
}
|
||||
return result;
|
||||
}
|
||||
std::string cb_frame::tag(const std::string& prefix) const
|
||||
std::string cb_frame::tag(const std::string& prefix, int prefixlen) const
|
||||
{
|
||||
char tag[48];
|
||||
if(prefix.length() == 0)
|
||||
snprintf(tag, sizeof(tag), "%04d 0x%03X ", msg_id, can_id);
|
||||
else
|
||||
snprintf(tag, sizeof(tag), "%-18s %04d 0x%03X ", prefix.c_str(), msg_id, can_id);
|
||||
snprintf(tag, sizeof(tag), "%-*s %04d 0x%03X ", prefixlen, prefix.c_str(), msg_id, can_id);
|
||||
return std::string(tag);
|
||||
}
|
||||
std::string cb_frame::to_string() const
|
||||
@ -147,22 +190,105 @@ namespace solar
|
||||
// Incorrect placement / misaligned arguments can lead to undefined behavior and processor crashes.
|
||||
std::string text = "";
|
||||
char hex[10];
|
||||
snprintf(hex, sizeof(hex), " %s", rtr ? "RTR" : " ");
|
||||
std::string line(hex);
|
||||
if (this->frame.empty()) {
|
||||
line += " <empty>";
|
||||
return line;
|
||||
std::string line;
|
||||
int n = 0;
|
||||
if(rtr) {
|
||||
line = "<remote request> ";
|
||||
text = " ";
|
||||
n = 6; // to align text output
|
||||
}
|
||||
for (const auto& byte : frame) {
|
||||
snprintf(hex, sizeof(hex), "%02X ", byte);
|
||||
line += hex;
|
||||
if(byte > 31 && byte < 127) {
|
||||
text += (char) byte;
|
||||
else {
|
||||
if (this->frame.empty()) {
|
||||
return "<empty>";
|
||||
}
|
||||
else {
|
||||
text += ".";
|
||||
}
|
||||
for (const auto& byte : frame) {
|
||||
n++;
|
||||
snprintf(hex, sizeof(hex), "%02X ", byte);
|
||||
line += hex;
|
||||
if(byte > 31 && byte < 127) {
|
||||
text += (char) byte;
|
||||
}
|
||||
else {
|
||||
text += ".";
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = n; i < 8; i++) {
|
||||
line += " ";
|
||||
text += " ";
|
||||
}
|
||||
return line + " " + text;
|
||||
}
|
||||
// helper function to extract a scaled double value from two bytes
|
||||
double cb_frame::get_double(uint8_t lsb, uint8_t msb, int inv_scale, bool is_signed)
|
||||
{
|
||||
int value = 0;
|
||||
if ((lsb == 0xFF && msb == 0xFF) || inv_scale == 0) {
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
if (is_signed) {
|
||||
value = static_cast<int16_t>((msb << 8) + lsb);
|
||||
} else {
|
||||
value = static_cast<uint16_t>((msb << 8) + lsb);
|
||||
}
|
||||
//ESP_LOGI("cb_frame::get_double", "0x%02X%02X unsigned %d, scale %d", msb, lsb, value, scale);
|
||||
return static_cast<double>(value) / inv_scale;
|
||||
}
|
||||
// Helper function to convert four scaled values into a byte stream
|
||||
// set scale to negative for signed values
|
||||
std::vector<uint8_t> cb_frame::get_byte_stream(double value1, int scale1, double value2, int scale2, double value3, int scale3, double value4, int scale4)
|
||||
{
|
||||
//ESP_LOGI("cb_frame::get_byte_stream", "1: %.3f 2: %.3f 3: %.3f 4: %.3f", value1, value2, value3, value4);
|
||||
std::vector<uint8_t> byte_stream(8, 0);
|
||||
int value;
|
||||
if(scale1 != 0) {
|
||||
value = (scale1 < 0) ? static_cast<int16_t>(value1 * -scale1) : static_cast<uint16_t>(value1 * scale1);
|
||||
byte_stream[0] = value % 256;
|
||||
byte_stream[1] = (value >> 8) % 256;
|
||||
}
|
||||
if(scale2 != 0) {
|
||||
value = (scale2 < 0) ? static_cast<int16_t>(value2 * -scale2) : static_cast<uint16_t>(value2 * scale2);
|
||||
byte_stream[2] = value % 256;
|
||||
byte_stream[3] = (value >> 8) % 256;
|
||||
}
|
||||
if(scale3 != 0) {
|
||||
value = (scale3 < 0) ? static_cast<int16_t>(value3 * -scale3) : static_cast<uint16_t>(value3 * scale3);
|
||||
byte_stream[4] = value % 256;
|
||||
byte_stream[5] = (value >> 8) % 256;
|
||||
}
|
||||
if(scale4 != 0) {
|
||||
value = (scale4 < 0) ? static_cast<int16_t>(value4 * -scale4) : static_cast<uint16_t>(value4 * scale4);
|
||||
byte_stream[6] = value % 256;
|
||||
byte_stream[7] = (value >> 8) % 256;
|
||||
}
|
||||
return byte_stream;
|
||||
}
|
||||
// Helper function to convert four scaled values into a byte stream
|
||||
// set scale to negative for signed values
|
||||
// Overloaded function to handle double scale for the fourth value
|
||||
std::vector<uint8_t> cb_frame::get_byte_stream(double value1, int scale1, double value2, int scale2, double value3, int scale3, double value4, double scale4)
|
||||
{
|
||||
std::vector<uint8_t> byte_stream(8, 0);
|
||||
int value;
|
||||
if(scale1 != 0) {
|
||||
value = (scale1 < 0) ? static_cast<int16_t>(value1 * -scale1) : static_cast<uint16_t>(value1 * scale1);
|
||||
byte_stream[0] = value % 256;
|
||||
byte_stream[1] = (value >> 8) % 256;
|
||||
}
|
||||
if(scale2 != 0) {
|
||||
value = (scale2 < 0) ? static_cast<int16_t>(value2 * -scale2) : static_cast<uint16_t>(value2 * scale2);
|
||||
byte_stream[2] = value % 256;
|
||||
byte_stream[3] = (value >> 8) % 256;
|
||||
}
|
||||
if(scale3 != 0) {
|
||||
value = (scale3 < 0) ? static_cast<int16_t>(value3 * -scale3) : static_cast<uint16_t>(value3 * scale3);
|
||||
byte_stream[4] = value % 256;
|
||||
byte_stream[5] = (value >> 8) % 256;
|
||||
}
|
||||
value = (scale4 < 0) ? static_cast<int16_t>(round(value4 * -scale4)) : static_cast<uint16_t>(round(value4 * scale4));
|
||||
byte_stream[6] = value % 256;
|
||||
byte_stream[7] = (value >> 8) % 256;
|
||||
return byte_stream;
|
||||
}
|
||||
|
||||
} // namespace solar
|
||||
45
cb_frame.h
45
cb_frame.h
@ -9,25 +9,27 @@ namespace solar
|
||||
{
|
||||
class cbf_store;
|
||||
class cb_frame {
|
||||
private:
|
||||
mutable bool publish; // whether this frame should be published
|
||||
public:
|
||||
enum cbf_store_sortcolumns : int
|
||||
enum cbf_sortcolumns : int
|
||||
{
|
||||
sisortNULL,
|
||||
sisortcanid,
|
||||
sisortframe,
|
||||
sisortrtr,
|
||||
sisortmsgid,
|
||||
sisortEND,
|
||||
sisortcase = SORTCASE, // case sensitive
|
||||
sisortreverse = SORTREVERSE, // reverse order
|
||||
sisortwild = WILDNULL, // an empty, or null entry equates to wildcard
|
||||
sistopcomparecol = STOPCOMPARE // stop compare after this column if both items to be compared are valid and a compare was possible
|
||||
sisortNULL,
|
||||
sisortcanid,
|
||||
sisortrtr,
|
||||
sisortframe,
|
||||
sisortmsgid,
|
||||
sisortEND,
|
||||
sisortcase = SORTCASE, // case sensitive
|
||||
sisortreverse = SORTREVERSE, // reverse order
|
||||
sisortwild = WILDNULL, // an empty, or null entry equates to wildcard
|
||||
sistopcomparecol = STOPCOMPARE // stop compare after this column if both items to be compared are valid and a compare was possible
|
||||
};
|
||||
int msg_id;
|
||||
bool rtr;
|
||||
bool rtr;
|
||||
uint32_t can_id;
|
||||
byte_vector frame;
|
||||
cb_frame() = default;
|
||||
cb_frame();
|
||||
cb_frame(int msg_id, uint32_t can_id);
|
||||
cb_frame(int msg_id, uint32_t can_id, const byte_vector& _frame, bool _rtr);
|
||||
void clear();
|
||||
@ -36,11 +38,26 @@ namespace solar
|
||||
virtual int compare(const cb_frame& b, const int *comparecolumns) const;
|
||||
virtual int compare(const cb_frame &b, int cmpflag, bool *stopcomparesignal, bool validnextcol) const;
|
||||
int compare_frame(const byte_vector& _frame) const;
|
||||
virtual std::string tag(const std::string& prefix = "") const;
|
||||
void setpublish(bool do_publish = true) const; // we promise only to modify the publish flag
|
||||
bool getpublish() const;
|
||||
virtual std::string tag(const std::string& prefix = "", int prefixlen = 18) const;
|
||||
virtual std::string to_string() const;
|
||||
virtual ~cb_frame() = default;
|
||||
// using default (compiler auto generated) copy and move constructors and assignment operators
|
||||
|
||||
/// Helper functions to convert four scaled values into a byte stream
|
||||
/// set scale to negative for signed values
|
||||
static std::vector<uint8_t> get_byte_stream(double value1, int scale1, double value2 = 0, int scale2 = 0, double value3 = 0, int scale3 = 0, double value4 = 0, int scale4 = 0);
|
||||
/// Overloaded function to handle double scale for the fourth value
|
||||
static std::vector<uint8_t> get_byte_stream(double value1, int scale1, double value2, int scale2, double value3, int scale3, double value4, double scale4);
|
||||
|
||||
/// helper function to extract a scaled double value from two bytes
|
||||
static double get_double(uint8_t lsb, uint8_t msb, int inv_scale, bool is_signed = false); //inv_scale is the reciprocal of scale factor
|
||||
bool send_frame(esphome::canbus::Canbus *canbus, bool extended_id = false, bool remote_transmission_request = false) const;
|
||||
static bool send_frame(esphome::canbus::Canbus *canbus, uint32_t can_id, const byte_vector& frame, bool extended_id = false, bool remote_transmission_request = false); // static version to send arbitrary frame
|
||||
};
|
||||
|
||||
extern const cb_frame emptyframe; // to return a reference to when no valid frame is found
|
||||
|
||||
} // namespace solar
|
||||
#endif // __SOLAR_CB_FRAME
|
||||
|
||||
@ -32,15 +32,16 @@ namespace solar
|
||||
}
|
||||
auto& kvp = *ret.first;
|
||||
auto& item = kvp.second;
|
||||
bool publish = false;
|
||||
if(item.update(storeitem, publish, comparecolumns, 1)) {
|
||||
auto updateresult = item.update(storeitem, comparecolumns, 1);
|
||||
if(updateresult & cbf_store::cbf_updateresult::stu_DUPLICATE) {
|
||||
// ESP_LOGI(item.store0.tag("== ST1 DUP == ").c_str(), item.store0.to_string().c_str());
|
||||
return publish;
|
||||
return updateresult & cbf_store::cbf_updateresult::stu_PUBLISH;
|
||||
}
|
||||
// try next store to see if it has a duplicate of new item
|
||||
if(item.update(storeitem, publish, comparecolumns, 2)) {
|
||||
updateresult = item.update(storeitem, comparecolumns, 2);
|
||||
if(updateresult & cbf_store::cbf_updateresult::stu_DUPLICATE) {
|
||||
// ESP_LOGI(item.store1.tag("== ST2 DUP == ").c_str(), item.store1.to_string().c_str());
|
||||
return publish;
|
||||
return updateresult & cbf_store::cbf_updateresult::stu_PUBLISH;
|
||||
}
|
||||
item.update(storeitem);
|
||||
//cache_map.erase(kvp.first);
|
||||
@ -49,6 +50,34 @@ namespace solar
|
||||
// ESP_LOGE(item.store0.tag("== ST1 ERR == ").c_str(), "Error re-inserting item into cache_map");
|
||||
// ESP_LOGE(item.store1.tag("== ST2 ERR == ").c_str(), "Error re-inserting item into cache_map");
|
||||
//}
|
||||
return publish;
|
||||
return false;
|
||||
}
|
||||
const cb_frame& cbf_cache::get_frame(uint32_t can_id) const
|
||||
{
|
||||
auto it = cache_map.find(can_id);
|
||||
if(it == cache_map.end())
|
||||
return emptyframe; // return reference to static empty frame if not found
|
||||
const auto& item = it->second;
|
||||
return item.get_frame();
|
||||
}
|
||||
bool cbf_cache::send_frame(esphome::canbus::Canbus *canbus, uint32_t can_id, bool extended_id, bool remote_transmission_request)
|
||||
{
|
||||
if(!this->hasitem(can_id))
|
||||
return false;
|
||||
const auto& cbf = get_frame(can_id);
|
||||
if(cbf.getpublish()) {
|
||||
return cbf.send_frame(canbus, extended_id, remote_transmission_request);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// static version to send arbitrary frame
|
||||
bool cbf_cache::send_frame(esphome::canbus::Canbus *canbus, uint32_t can_id, const byte_vector& frame, bool extended_id, bool remote_transmission_request)
|
||||
{
|
||||
return cb_frame::send_frame(canbus, can_id, frame, extended_id, remote_transmission_request);
|
||||
}
|
||||
bool cbf_cache::send_request(esphome::canbus::Canbus *canbus, uint32_t can_id, bool extended_id)
|
||||
{
|
||||
return cb_frame::send_frame(canbus, can_id, {}, extended_id, true);
|
||||
}
|
||||
|
||||
} // namespace solar
|
||||
@ -12,9 +12,8 @@ using namespace esphome;
|
||||
namespace solar
|
||||
{
|
||||
class cbf_cache {
|
||||
private:
|
||||
std::map<uint32_t, cbf_cache_item> cache_map; // map of CAN IDs to cache items
|
||||
public:
|
||||
std::map<uint32_t, cbf_cache_item> cache_map; // map of CAN IDs to cache items
|
||||
cbf_cache() = default;
|
||||
void clear();
|
||||
int size() const;
|
||||
@ -23,7 +22,13 @@ namespace solar
|
||||
const cbf_cache_item& getitem(uint32_t can_id) const;
|
||||
// Add a new item to the cache or update an existing one
|
||||
bool additem(const cbf_store& item);
|
||||
const cb_frame& get_frame(uint32_t can_id) const;
|
||||
virtual ~cbf_cache() = default; // virtual destructor for base class
|
||||
bool send_frame(esphome::canbus::Canbus *canbus, uint32_t can_id, bool extended_id = false, bool remote_transmission_request = false);
|
||||
static bool send_frame(esphome::canbus::Canbus *canbus, uint32_t can_id, const byte_vector& frame, bool extended_id = false, bool remote_transmission_request = false); // static version to send arbitrary frame
|
||||
static bool send_request(esphome::canbus::Canbus *canbus, uint32_t can_id, bool extended_id = false); // static version to send remote transmission request frame
|
||||
// using default (compiler auto generated) copy and move constructors and assignment operators
|
||||
|
||||
};
|
||||
|
||||
} // namespace solar
|
||||
|
||||
@ -15,10 +15,7 @@ namespace solar
|
||||
this->store0 = store0.clone();
|
||||
this->store1 = store0.clone();
|
||||
this->store0->id = 1;
|
||||
//this->store1->clear();
|
||||
this->store1->id = 2;
|
||||
//ESP_LOGI( this->store0->tag("cache_item CTOR1A ").c_str(), "%-20s %s", "Created cache item", this->store0->to_string().c_str());
|
||||
//ESP_LOGI( this->store1->tag("cache_item CTOR1B ").c_str(), "%-20s %s", "Created cache item", this->store1->to_string().c_str());
|
||||
}
|
||||
void cbf_cache_item::clear()
|
||||
{
|
||||
@ -32,60 +29,69 @@ namespace solar
|
||||
}
|
||||
bool cbf_cache_item::update(const cbf_store& newitem)
|
||||
{
|
||||
//std::string posttag0 = std::string("cache_item UPD ST1");
|
||||
//std::string posttag1 = std::string("cache_item UPD ST2");
|
||||
// ESP_LOGI(store0->tag(posttag0).c_str(), "VALID: %s %s", store0->is_valid() ? "Y" : "N", store0->to_string().c_str());
|
||||
// ESP_LOGI(store1->tag(posttag1).c_str(), "VALID: %s %s", store1->is_valid() ? "Y" : "N", store1->to_string().c_str());
|
||||
if(!this->store0->is_valid()) {
|
||||
store0 = newitem.clone();
|
||||
store0->id = 1;
|
||||
// ESP_LOGI(store0->tag("== ST1 INV NEW ==").c_str(), store0->to_string().c_str());
|
||||
return true;
|
||||
}
|
||||
if(!this->store1->is_valid()) {
|
||||
store1 = newitem.clone();
|
||||
store1->id = 2;
|
||||
// ESP_LOGI(store1->tag("== ST2 INV NEW ==").c_str(), store1->to_string().c_str());
|
||||
return true;
|
||||
}
|
||||
bool result = store1->last_timestamp > store0->last_timestamp;
|
||||
if(result) {
|
||||
store0 = newitem.clone();
|
||||
this->store0->id = 1;
|
||||
// ESP_LOGI(store0->tag("== ST1 OLD NEW ==").c_str(), store0->to_string().c_str());
|
||||
}
|
||||
else {
|
||||
store1 = newitem.clone();
|
||||
this->store1->id = 2;
|
||||
// ESP_LOGI(store1->tag("== OLD ST2 NEW ==").c_str(), store1->to_string().c_str());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
bool cbf_cache_item::update(const cbf_store& newitem, bool& publish, const int *comparecolumns, int store_selector)
|
||||
cbf_store::cbf_updateresult cbf_cache_item::update(const cbf_store& newitem, const int *comparecolumns, int store_selector)
|
||||
{
|
||||
bool result = false;
|
||||
cbf_store::cbf_updateresult result = cbf_store::cbf_updateresult::stu_NONE;
|
||||
switch(store_selector) {
|
||||
case 2:
|
||||
result = this->store1->update(newitem, publish, comparecolumns);
|
||||
result = this->store1->update(newitem, comparecolumns);
|
||||
break;
|
||||
default:
|
||||
result = this->store0->update(newitem, publish, comparecolumns);
|
||||
result = this->store0->update(newitem, comparecolumns);
|
||||
break;
|
||||
}
|
||||
//std::string posttag = std::string("cache_item ") + (result ? "UPD" : "NUP") + " ST" + std::to_string(store_selector) + " ";
|
||||
//if(store_selector == 1 ) {
|
||||
// ESP_LOGI(store1->tag(posttag).c_str(), store1->to_string().c_str());
|
||||
//} else {
|
||||
// ESP_LOGI(store0->tag(posttag).c_str(), store0->to_string().c_str());
|
||||
//}
|
||||
return result;
|
||||
}
|
||||
const cb_frame& cbf_cache_item::get_frame() const
|
||||
{
|
||||
return get_store(); // return most recent valid store's frame
|
||||
}
|
||||
const cbf_store& cbf_cache_item::get_store() const
|
||||
{
|
||||
if(this->store0->is_valid() && !this->store1->is_valid()) {
|
||||
return *store0;
|
||||
}
|
||||
if(!this->store0->is_valid() && this->store1->is_valid()) {
|
||||
return *store1;
|
||||
}
|
||||
if(this->store0->is_valid() && this->store1->is_valid()) {
|
||||
if(this->store0->last_timestamp >= this->store1->last_timestamp) {
|
||||
return *this->store0;
|
||||
} else {
|
||||
return *this->store1;
|
||||
}
|
||||
}
|
||||
return *this->store0; // no valid stores, but return store0 which is always present
|
||||
}
|
||||
std::string cbf_cache_item::tag(const std::string& prefix) const
|
||||
{
|
||||
char tag[24];
|
||||
snprintf(tag, sizeof(tag), "%-18s ", prefix.c_str());
|
||||
return std::string(tag);
|
||||
}
|
||||
return get_store().tag(prefix, prefix.length());
|
||||
}
|
||||
std::string cbf_cache_item::to_string() const
|
||||
{
|
||||
return get_store().to_string();
|
||||
}
|
||||
std::string cbf_cache_item::tag0(const std::string& prefix) const
|
||||
{
|
||||
return store0->tag(prefix);
|
||||
@ -94,15 +100,16 @@ namespace solar
|
||||
{
|
||||
return store1->tag(prefix);
|
||||
}
|
||||
std::string cbf_cache_item::to_string() const
|
||||
std::string cbf_cache_item::st0_tostring() const
|
||||
{
|
||||
// Be extra careful with the placement of printf format specifiers and their corresponding arguments.
|
||||
// Incorrect placement / misaligned arguments can lead to undefined behavior and processor crashes.
|
||||
char buffer[180];
|
||||
// trim
|
||||
auto trimmedtag0 = trim(tag0());
|
||||
auto trimmedtag1 = trim(tag1());
|
||||
snprintf(buffer, sizeof(buffer), "ST1: [%s] %s | ST2: [%s] %s", trimmedtag0.c_str(), store0->to_string().c_str(), trimmedtag1.c_str(), store1->to_string().c_str());
|
||||
char buffer[150];
|
||||
snprintf(buffer, sizeof(buffer), "ST1: [%s] %s", trim(tag0()).c_str(), store0->to_string().c_str());
|
||||
return std::string(buffer);
|
||||
}
|
||||
std::string cbf_cache_item::st1_tostring() const
|
||||
{
|
||||
char buffer[150];
|
||||
snprintf(buffer, sizeof(buffer), "ST2: [%s] %s", trim(tag1()).c_str(), store1->to_string().c_str());
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
|
||||
@ -20,12 +20,15 @@ namespace solar
|
||||
void clear();
|
||||
void swap(cbf_cache_item &s);
|
||||
bool update(const cbf_store& newitem);
|
||||
bool update(const cbf_store& newitem, bool& publish, const int *comparecolumns, int store_selector);
|
||||
cbf_store::cbf_updateresult update(const cbf_store& newitem, const int *comparecolumns, int store_selector);
|
||||
const cb_frame& get_frame() const; // returns the most recent valid frame
|
||||
const cbf_store& get_store() const; // returns the most recent valid store
|
||||
virtual std::string tag0(const std::string& prefix = "") const;
|
||||
virtual std::string tag1(const std::string& prefix = "") const;
|
||||
virtual std::string tag(const std::string& prefix = "") const;
|
||||
virtual std::string to_string() const;
|
||||
|
||||
virtual std::string st0_tostring() const; // string of store 0
|
||||
virtual std::string st1_tostring() const; // string of store 1
|
||||
// the default copy and move constructors and assignment operators are fine
|
||||
// because shared_ptr takes care of the underlying memory management
|
||||
cbf_cache_item(const cbf_cache_item& b) = default;
|
||||
|
||||
@ -4,14 +4,15 @@ namespace solar
|
||||
{
|
||||
// see common.h for definition of publish_spec_t
|
||||
// publish_spec_t(int on_count, int interval, int timeout)
|
||||
const publish_spec_t cbf_pylon::publish_spec = publish_spec_t(3, 10, 30); // default publish spec for Pylontech battery messages
|
||||
const publish_spec_t cbf_pylon::publish_spec = publish_spec_t(3, 15, 30); // default publish spec for Pylontech battery messages
|
||||
const publish_spec_t cbf_pylon::rtr_publish_spec = publish_spec_t(2, 10, 15); // for remote transmission requests
|
||||
|
||||
cbf_pylon& cbf_pylon::operator=(cbf_pylon&& src)
|
||||
{
|
||||
if (this != &src) {
|
||||
cb_frame::operator=(std::move(src));
|
||||
src.clear();
|
||||
ESP_LOGI(tag("pylon MOASS").c_str(), "%-20s %s", "Assigned pylon", this->to_string().c_str());
|
||||
//ESP_LOGI(tag("pylon MOASS").c_str(), "%-20s %s", "Assigned pylon", this->to_string().c_str());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -19,6 +20,13 @@ namespace solar
|
||||
{
|
||||
cb_frame::clear();
|
||||
}
|
||||
|
||||
// float cbf_pylon::_get_battery_charge_voltage_limit() const
|
||||
// {
|
||||
// const auto& x = this->frame;
|
||||
// return 0.1 * (float)((x[1] << 8) + x[0]);
|
||||
// }
|
||||
|
||||
// Function to build a message from the pylon canbus frame
|
||||
std::string cbf_pylon::to_string() const
|
||||
{
|
||||
@ -27,6 +35,9 @@ namespace solar
|
||||
{
|
||||
case CB_BATTERY_LIMITS:
|
||||
{
|
||||
if(rtr) {
|
||||
return "Request for BATTERY LIMITS info";
|
||||
}
|
||||
if (this->frame.size() < 6) {
|
||||
return "Invalid frame size for CB_BATTERY_LIMITS";
|
||||
}
|
||||
@ -40,6 +51,9 @@ namespace solar
|
||||
break;
|
||||
case CB_BATTERY_STATE:
|
||||
{
|
||||
if(rtr) {
|
||||
return "Request for BATTERY STATE info";
|
||||
}
|
||||
if (this->frame.size() < 4) {
|
||||
return "Invalid frame size for CB_BATTERY_STATE";
|
||||
}
|
||||
@ -52,6 +66,9 @@ namespace solar
|
||||
break;
|
||||
case CB_BATTERY_STATUS:
|
||||
{
|
||||
if(rtr) {
|
||||
return "Request for BATTERY STATUS info";
|
||||
}
|
||||
if (this->frame.size() < 6) {
|
||||
return "Invalid frame size for CB_BATTERY_STATUS";
|
||||
}
|
||||
@ -65,6 +82,9 @@ namespace solar
|
||||
break;
|
||||
case CB_BATTERY_FAULT:
|
||||
{
|
||||
if(rtr) {
|
||||
return "Request for BATTERY FAULT info";
|
||||
}
|
||||
if (this->frame.size() < 8) {
|
||||
return "Invalid frame size for CB_BATTERY_FAULT";
|
||||
}
|
||||
@ -96,6 +116,9 @@ namespace solar
|
||||
break;
|
||||
case CB_BATTERY_REQUEST_FLAGS:
|
||||
{
|
||||
if(rtr) {
|
||||
return "Request for BATTERY REQUEST FLAGS info";
|
||||
}
|
||||
if (this->frame.size() < 1) {
|
||||
return "Invalid frame size for CB_BATTERY_REQUEST_FLAGS";
|
||||
}
|
||||
@ -112,18 +135,24 @@ namespace solar
|
||||
break;
|
||||
case CB_BATTERY_MANUFACTURER:
|
||||
{
|
||||
if (this->frame.size() < 8) {
|
||||
return "Invalid frame size for CB_BATTERY_MANUFACTURER";
|
||||
}
|
||||
const auto& x = this->frame;
|
||||
// Manufacturer name is in the first 8 bytes, padded with spaces
|
||||
// Convert to string and trim trailing spaces
|
||||
std::string manufacturer(reinterpret_cast<const char*>(x.data()), 8);
|
||||
manufacturer.erase(std::find_if(manufacturer.rbegin(), manufacturer.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), manufacturer.end());
|
||||
return "BATTERY OEM: " + manufacturer;
|
||||
if(rtr) {
|
||||
return "Request for BATTERY MANUFACTURER info";
|
||||
}
|
||||
if (this->frame.size() < 8) {
|
||||
return "Invalid frame size for CB_BATTERY_MANUFACTURER";
|
||||
}
|
||||
const auto& x = this->frame;
|
||||
// Manufacturer name is in the first 8 bytes, padded with spaces
|
||||
// Convert to string and trim trailing spaces
|
||||
std::string manufacturer(reinterpret_cast<const char*>(x.data()), 8);
|
||||
manufacturer.erase(std::find_if(manufacturer.rbegin(), manufacturer.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), manufacturer.end());
|
||||
return "BATTERY OEM: " + manufacturer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(rtr) {
|
||||
return "Request for unknown CAN ID info";
|
||||
}
|
||||
return "Unknown CAN ID";
|
||||
}
|
||||
} // namespace solar
|
||||
60
cbf_pylon.h
60
cbf_pylon.h
@ -8,70 +8,30 @@ using namespace esphome;
|
||||
|
||||
namespace solar
|
||||
{
|
||||
|
||||
class cbf_pylon : virtual public cb_frame {
|
||||
|
||||
public:
|
||||
// Pylontech publish spec
|
||||
// This is used to determine when to publish the battery data from the Pylontech battery
|
||||
static const publish_spec_t publish_spec; // default publish spec for Pylontech battery messages
|
||||
static const publish_spec_t rtr_publish_spec; // for remote transmission requests
|
||||
|
||||
// Pylontech battery CAN IDs
|
||||
// All unverified IDs are taken from the Pylontech CAN protocol documentation
|
||||
// https://domosimple.eu/en/documentation/manuels/pylontech-can-bus-protocole
|
||||
// VERIFIED IDs have been confirmed by capturing actual CAN bus traffic from a Pylontech battery
|
||||
static const int CB_BATTERY_LIMITS = 0x351; // VERIFIED: Pylontech battery max charging/discharging values message
|
||||
static const int CB_BATTERY_SETTING2 = 0x352; // used for Pylontech batteries
|
||||
static const int CB_BATTERY_SETTING3 = 0x353; // used for Pylontech batteries
|
||||
static const int CB_BATTERY_SETTING4 = 0x354; // used for Pylontech batteries
|
||||
static const int CB_BATTERY_STATE = 0x355; // VERIFIED: Pylontech battery state message
|
||||
static const int CB_BATTERY_STATUS = 0x356; // VERIFIED: Pylontech battery status message
|
||||
static const int CB_BATTERY_ERROR = 0x357;
|
||||
static const int CB_BATTERY_WARNING = 0x358;
|
||||
static const int CB_BATTERY_FAULT = 0x359; // VERIFIED: Pylontech battery fault message
|
||||
static const int CB_BATTERY_REQUEST = 0x35A;
|
||||
static const int CB_BATTERY_RESPONSE = 0x35B;
|
||||
static const int CB_BATTERY_REQUEST_FLAGS = 0x35C; // VERIFIED: Pylontech battery request flag message
|
||||
static const int CB_BATTERY_MANUFACTURER_ID = 0x35D;
|
||||
static const int CB_BATTERY_MODEL_ID = 0x35E;
|
||||
static const int CB_BATTERY_MANUFACTURER = 0x35E; // VERIFIED: Pylontech battery manufacturer message
|
||||
static const int CB_BATTERY_MODEL = 0x35D;
|
||||
static const int CB_BATTERY_SERIAL_NUMBER = 0x35F;
|
||||
static const int CB_BATTERY_VERSION = 0x360;
|
||||
static const int CB_BATTERY_CAPACITY = 0x361;
|
||||
static const int CB_BATTERY_TEMPERATURE = 0x362;
|
||||
static const int CB_BATTERY_VOLTAGE = 0x363;
|
||||
static const int CB_BATTERY_CURRENT = 0x364;
|
||||
static const int CB_BATTERY_SOC = 0x365;
|
||||
static const int CB_BATTERY_SOH = 0x366;
|
||||
static const int CB_BATTERY_CHARGE_POWER = 0x367;
|
||||
static const int CB_BATTERY_DISCHARGE_POWER = 0x368;
|
||||
static const int CB_BATTERY_CHARGE_ENERGY = 0x369;
|
||||
static const int CB_BATTERY_DISCHARGE_ENERGY = 0x36A;
|
||||
static const int CB_BATTERY_CHARGE_CYCLES = 0x36B;
|
||||
static const int CB_BATTERY_CHARGE_LIMIT = 0x36C;
|
||||
static const int CB_BATTERY_DISCHARGE_LIMIT = 0x36D;
|
||||
static const int CB_BATTERY_CHARGE_MODE = 0x36E;
|
||||
static const int CB_BATTERY_DISCHARGE_MODE = 0x36F;
|
||||
static const int CB_BATTERY_CHARGE_STATUS = 0x370;
|
||||
static const int CB_BATTERY_DISCHARGE_STATUS = 0x371;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_COUNT = 0x372;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_LIMIT = 0x373;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_STATUS = 0x374;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_MODE = 0x375;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_LIMIT_STATUS = 0x376;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_MODE_STATUS = 0x377;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_LIMIT_MODE = 0x378;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_LIMIT_MODE_STATUS = 0x379;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_LIMIT_MODE_STATUS2 = 0x37A;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_LIMIT_MODE_STATUS3 = 0x37B;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_LIMIT_MODE_STATUS4 = 0x37C;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_LIMIT_MODE_STATUS5 = 0x37D;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_LIMIT_MODE_STATUS6 = 0x37E;
|
||||
static const int CB_BATTERY_CHARGE_CYCLE_LIMIT_MODE_STATUS7 = 0x37F;
|
||||
// Pylontech battery publish spec
|
||||
// This is used to determine when to publish the battery data
|
||||
static const publish_spec_t publish_spec;
|
||||
|
||||
//Property<int, cbf_pylon> battery_charge_voltage_limit {this, &cbf_pylon::_set_battery_charge_voltage_limit, &cbf_pylon::_get_battery_charge_voltage_limit };
|
||||
//Property<float, cbf_pylon> battery_charge_voltage_limit {this, &cbf_pylon::_get_battery_charge_voltage_limit};
|
||||
|
||||
cbf_pylon() = default;
|
||||
cbf_pylon(int msg_id, uint32_t can_id, const byte_vector& frame, bool rtr);
|
||||
void clear();
|
||||
std::string to_string() const override;
|
||||
virtual std::string to_string() const override;
|
||||
cbf_pylon& operator=(cbf_pylon&& src); // required due to double inheritance in cbf_store_pylon
|
||||
// using default (compiler auto generated) copy and move constructors and assignment operators
|
||||
};
|
||||
|
||||
@ -64,24 +64,29 @@ namespace solar
|
||||
{
|
||||
return (this->last_timestamp == 0) || ((currenttime - this->last_timestamp) >= timeout_interval);
|
||||
}
|
||||
bool cbf_store::update(const cbf_store& newitem, bool& publish, const int *comparecolumns)
|
||||
cbf_store::cbf_updateresult cbf_store::update(const cbf_store& newitem, const int *comparecolumns)
|
||||
{
|
||||
ESP_LOGW(this->tag("store UPDATE").c_str(), "%-20s %s", "Default update call", this->to_string().c_str()); // this should happen as all updating should be called from derived classes, i.e. providing publish_spec as a parameter
|
||||
return update(newitem, publish_spec_t{1, 5, 10}, publish, comparecolumns); // we are forced to instantiate this class, so we provide a default implementation
|
||||
ESP_LOGW(this->tag("store UPDATE").c_str(), "%-20s %s", "Default update call", this->to_string().c_str()); // this should happen as all updating should be called from derived classes, i.e. providing the publish_specs as parameters
|
||||
return update(newitem, publish_spec_t{1, 5, 10}, publish_spec_t{1, 5, 10}, comparecolumns); // we are forced to instantiate this class, so we provide a default implementation
|
||||
}
|
||||
bool cbf_store::update(const cbf_store& newitem, publish_spec_t publish_spec, bool& publish, const int *comparecolumns)
|
||||
cbf_store::cbf_updateresult cbf_store::update(const cbf_store& newitem, publish_spec_t publish_spec, publish_spec_t rtr_publish_spec, const int *comparecolumns)
|
||||
{
|
||||
if(!is_valid()) {
|
||||
return false;
|
||||
return cbf_updateresult::stu_NONE; // cannot update an invalid store
|
||||
}
|
||||
auto pbspec = rtr ? rtr_publish_spec : publish_spec;
|
||||
time_t newtime = newitem.last_timestamp;
|
||||
bool publish_expired = this->is_publish_expired(newtime, publish_spec.interval);
|
||||
bool validity_expired = this->is_validity_expired(newtime, publish_spec.timeout);
|
||||
bool publish_expired = this->is_publish_expired(newtime, pbspec.interval);
|
||||
bool validity_expired = this->is_validity_expired(newtime, pbspec.timeout);
|
||||
bool isduplicate = this->compare(newitem, comparecolumns) == 0;
|
||||
time_t reset_timer = this->first_timestamp + publish_spec.interval - newtime;
|
||||
auto ntstime = ESPTime::from_epoch_local(newtime).strftime("%H:%M:%S");
|
||||
time_t reset_timer = this->first_timestamp + pbspec.interval - newtime;
|
||||
int timediff = is_valid() ? (int)(newtime - this->last_timestamp) : -1;
|
||||
//ESP_LOGI(this->tag("store UPDATE Bef").c_str(), "%s Td:%2d To:%s Ex:%s Rt:%2d Nts: %s %s", isduplicate ? "DUP" : "NEW", timediff, validity_expired ? "Y" : "N", publish_expired ? "Y" : "N", static_cast<int>(reset_timer), ntstime.c_str(), this->to_string().c_str());
|
||||
auto result = isduplicate ? cbf_updateresult::stu_DUPLICATE : cbf_updateresult::stu_NONE;
|
||||
// auto ftstime = ESPTime::from_epoch_local(this->first_timestamp).strftime("%H:%M:%S");
|
||||
// auto ltstime = ESPTime::from_epoch_local(this->last_timestamp).strftime("%H:%M:%S");
|
||||
// auto ntstime = ESPTime::from_epoch_local(newtime).strftime("%H:%M:%S");
|
||||
// if(rtr)
|
||||
// ESP_LOGI(this->tag("store UPDATE").c_str(), "A: %s PBS %d,%d,%d PE:%s VE:%s DUP:%s FTS %s LTS %s NTS %s RES[D%s P%s]", rtr ? "RTR" : "NML", pbspec.on_count, pbspec// .interval, pbspec.timeout, publish_expired ? "Y" : "N", validity_expired ? "Y" : "N", isduplicate ? "Y" : "N", ftstime.c_str(), ltstime.c_str(), ntstime.c_str(),// result & cbf_updateresult::stu_DUPLICATE ? "Y" : "N", result & cbf_updateresult::stu_PUBLISH ? "Y" : "N");
|
||||
if(validity_expired) {
|
||||
*this = newitem;
|
||||
if(!isduplicate) {
|
||||
@ -91,15 +96,22 @@ namespace solar
|
||||
}
|
||||
if(isduplicate || publish_expired) {
|
||||
this->count++;
|
||||
publish = (this->count == publish_spec.on_count);
|
||||
if(this->count == pbspec.on_count)
|
||||
this->setpublish(); // must be reset by caller after publish
|
||||
if(this->getpublish())
|
||||
result = static_cast<cbf_updateresult>(result | cbf_updateresult::stu_PUBLISH);
|
||||
this->last_timestamp = newtime;
|
||||
if(reset_timer <= 0) {
|
||||
this->first_timestamp = newtime;
|
||||
this->count = 1;
|
||||
}
|
||||
}
|
||||
//ESP_LOGI(this->tag("store UPDATE Aft").c_str(), "%s Td:%2d To:%s Ex:%s Rt:%2d Pu:%s Nts: %s %s", isduplicate ? "DUP" : "NEW", timediff, validity_expired ? "Y" : "N", publish_expired ? "Y" : "N", static_cast<int>(reset_timer), publish ? "Y" : "N", ntstime.c_str(), this->to_string().c_str());
|
||||
return isduplicate;
|
||||
// ftstime = ESPTime::from_epoch_local(this->first_timestamp).strftime("%H:%M:%S");
|
||||
// ltstime = ESPTime::from_epoch_local(this->last_timestamp).strftime("%H:%M:%S");
|
||||
// if(rtr)
|
||||
// ESP_LOGI(this->tag("store UPDATE").c_str(), "B: %s PBS %d,%d,%d PE:%s VE:%s DUP:%s FTS %s LTS %s NTS %s RES[D%s P%s]", rtr ? "RTR" : "NML", pbspec.on_count, pbspec.interval, pbspec.timeout, publish_expired ? "Y" : "N", validity_expired ? "Y" : "N", isduplicate ? "Y" : "N", ftstime.c_str(), ltstime.c_str(), ntstime.c_str(), result & cbf_updateresult::stu_DUPLICATE ? "Y" : "N", result & cbf_updateresult::stu_PUBLISH ? "Y" : "N");
|
||||
|
||||
return result;
|
||||
}
|
||||
int cbf_store::compare(const cbf_store& b, const int *comparecolumns) const
|
||||
{
|
||||
@ -199,15 +211,15 @@ namespace solar
|
||||
result = -result;
|
||||
return result;
|
||||
}
|
||||
std::string cbf_store::tag(const std::string& prefix) const
|
||||
std::string cbf_store::tag(const std::string& prefix, int prefixlen) const
|
||||
{
|
||||
// Be extra careful with the placement of printf format specifiers and their corresponding arguments.
|
||||
// Incorrect placement / misaligned arguments can lead to undefined behavior and processor crashes.
|
||||
char tag[48];
|
||||
if(prefix.length() == 0)
|
||||
snprintf(tag, sizeof(tag), "%04d id%d 0x%03X ", msg_id, id, can_id);
|
||||
else
|
||||
snprintf(tag, sizeof(tag), "%-18s %04d id%d 0x%03X ", prefix.c_str(), msg_id, id, can_id);
|
||||
snprintf(tag, sizeof(tag), "#%04d s%d 0x%03X %s", msg_id, id, can_id, getpublish() ? "P" : " ");
|
||||
else
|
||||
snprintf(tag, sizeof(tag), "%-*s #%04d s%d 0x%03X %s", prefixlen, prefix.c_str(), msg_id, id, can_id, getpublish() ? "P" : " ");
|
||||
return std::string(tag);
|
||||
}
|
||||
std::string cbf_store::to_string() const
|
||||
|
||||
20
cbf_store.h
20
cbf_store.h
@ -16,12 +16,12 @@ namespace solar
|
||||
int count; // how many times a duplicate of this frame was received; used to signal publish
|
||||
time_t first_timestamp; // used for checking whether updateinterval has expired, i.e. to force a publish
|
||||
time_t last_timestamp; // used for choosing which store to overwrite with new (different) frame data
|
||||
enum cbf_store_sortcolumns : int
|
||||
enum cbf_sortcolumns : int
|
||||
{
|
||||
sisortNULL,
|
||||
sisortcanid = cb_frame::sisortcanid,
|
||||
sisortframe = cb_frame::sisortframe,
|
||||
sisortrtr = cb_frame::sisortrtr,
|
||||
sisortframe = cb_frame::sisortframe,
|
||||
sisortmsgid = cb_frame::sisortmsgid,
|
||||
sisortcount,
|
||||
sisortfirst_timestamp,
|
||||
@ -32,6 +32,14 @@ namespace solar
|
||||
sisortwild = WILDNULL, // where applicable, an empty or null entry equates to wildcard
|
||||
sistopcomparecol = STOPCOMPARE // stop compare after this column if both items to be compared are valid and a compare was possible
|
||||
};
|
||||
|
||||
enum cbf_updateresult : int
|
||||
{
|
||||
stu_NONE = 0, // no update
|
||||
stu_DUPLICATE = 0b01, // updated with new timestamps no publish
|
||||
stu_PUBLISH = 0b10, // can publish data
|
||||
stu_DUPLICATE_PUBLISH = 0b11, // updated with new timestamps; can publish data
|
||||
};
|
||||
cbf_store() = delete; // default constructor not allowed
|
||||
cbf_store(int msg_id, uint32_t can_id, int id);
|
||||
cbf_store(int msg_id, uint32_t can_id, int id, time_t _first_timestamp, time_t _last_timestamp);
|
||||
@ -43,12 +51,12 @@ namespace solar
|
||||
|
||||
std::shared_ptr<cbf_store> clone() const;
|
||||
int compare(const cbf_store& b, const int *comparecolumns) const;
|
||||
std::string tag(const std::string& prefix = "") const override;
|
||||
std::string to_string() const override;
|
||||
virtual std::string tag(const std::string& prefix = "", int prefixlen = 18) const override;
|
||||
virtual std::string to_string() const override;
|
||||
bool is_publish_expired(time_t currenttime, int update_interval) const;
|
||||
bool is_validity_expired(time_t currenttime, int timeout_interval) const;
|
||||
bool update(const cbf_store& newitem, publish_spec_t publish_spec, bool& publish, const int *comparecolumns);
|
||||
virtual bool update(const cbf_store& newitem, bool& publish, const int *comparecolumns); // should be pure virtual function, but we need to instantiate this class
|
||||
cbf_updateresult update(const cbf_store& newitem, publish_spec_t publish_spec, publish_spec_t rtr_publish_spec, const int *comparecolumns);
|
||||
virtual cbf_updateresult update(const cbf_store& newitem, const int *comparecolumns); // should be pure virtual function, but we need to instantiate this class
|
||||
|
||||
private:
|
||||
int compare(const cbf_store &b, int cmpflag, bool *stopcomparesignal, bool validnextcol) const;
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
|
||||
namespace solar
|
||||
{
|
||||
cbf_store_pylon::cbf_store_pylon(int msg_id, uint32_t can_id, const byte_vector& _frame, bool _rtr, time_t timestamp)
|
||||
: cb_frame(msg_id, can_id, _frame, _rtr), cbf_store(msg_id, can_id, 0, timestamp, timestamp)
|
||||
cbf_store_pylon::cbf_store_pylon(int msg_id, uint32_t can_id, const byte_vector& frame, bool rtr, time_t timestamp)
|
||||
: cb_frame(msg_id, can_id, frame, rtr), cbf_store(msg_id, can_id, 0, timestamp, timestamp) //, cbf_pylon(msg_id, can_id, frame, rtr)
|
||||
{
|
||||
this->id = 0;
|
||||
this->count = 0;
|
||||
@ -58,14 +58,14 @@ namespace solar
|
||||
cb_frame::swap(s);
|
||||
cbf_store::swap(s);
|
||||
}
|
||||
bool cbf_store_pylon::update(const cbf_store& newitem, bool& publish, const int *comparecolumns)
|
||||
cbf_store::cbf_updateresult cbf_store_pylon::update(const cbf_store& newitem, const int *comparecolumns)
|
||||
{
|
||||
//ESP_LOGI(tag("store_pylon UPDATE").c_str(), "%-20s %s", "Updating store_pylon", this->to_string().c_str());
|
||||
return cbf_store::update(newitem, publish_spec, publish, comparecolumns);
|
||||
return cbf_store::update(newitem, publish_spec, rtr_publish_spec, comparecolumns);
|
||||
}
|
||||
std::string cbf_store_pylon::to_string() const
|
||||
{
|
||||
return cbf_store::to_string() + " " + cbf_pylon::to_string();
|
||||
return cb_frame::to_string() + " " + cbf_pylon::to_string();
|
||||
}
|
||||
|
||||
} // namespace solar
|
||||
@ -18,8 +18,8 @@ namespace solar
|
||||
std::shared_ptr<cbf_store_pylon> clone() const;
|
||||
void clear();
|
||||
void swap(cbf_store_pylon &s);
|
||||
virtual bool update(const cbf_store& newitem, bool& publish, const int *comparecolumns) override;
|
||||
std::string to_string() const override;
|
||||
virtual cbf_store::cbf_updateresult update(const cbf_store& newitem, const int *comparecolumns) override;
|
||||
virtual std::string to_string() const override;
|
||||
|
||||
cbf_store_pylon(const cbf_store_pylon& b);
|
||||
cbf_store_pylon& operator=(const cbf_store_pylon& b);
|
||||
|
||||
2
common.h
2
common.h
@ -12,6 +12,8 @@ namespace solar
|
||||
#define SEARCHWILD 0x0100000 // do wildcard comparison (only searchkey should contain wildcards)
|
||||
#define num_compare(a, b) ((a) > (b)) ? +1 : ((a) < (b)) ? -1 : 0
|
||||
#define bool_compare(a, b) ((!(a) && !(b)) || ((a) && (b))) ? 0 : (a) ? +1 : -1
|
||||
#define max(a, b) ((a) > (b)) ? (a) : (b)
|
||||
#define min(a, b) ((a) < (b)) ? (a) : (b)
|
||||
|
||||
typedef unsigned int uint;
|
||||
typedef std::vector<uint8_t> byte_vector;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user