From 20f30d7c02cfdf35991cb5cbe2d0c71a7d9104a4 Mon Sep 17 00:00:00 2001 From: Nils Schulte Date: Sun, 14 Jan 2024 20:02:01 +0100 Subject: [PATCH] wip --- include/simplesync.hpp | 230 ++++++++++++++++++----------------------- 1 file changed, 103 insertions(+), 127 deletions(-) diff --git a/include/simplesync.hpp b/include/simplesync.hpp index a6e6cac..a8ed24f 100644 --- a/include/simplesync.hpp +++ b/include/simplesync.hpp @@ -1,23 +1,28 @@ #ifndef SIMPLESYNC_HPP #define SIMPLESYNC_HPP -#include -#include -#include -#include -#include -#include - #ifdef ARDUINO #include #ifdef __AVR__ #include "include/nonstd_functional.hpp" using nonstd::function; #else /* ndef __AVR__ */ -using std::function; +#define STDCLIB #endif #else /* ndef ARDUINO */ +#define STDCLIB +#endif +#ifdef STDCLIB +#include +#include +#include +#include +#include +#include +#include +#include using std::function; +using std::string; #endif namespace simplesync { @@ -127,97 +132,109 @@ inline uint16_t calc_fletcher_checksum(uint8_t *buf, unsigned int buf_size) { return (c1 << 8 | c0); } -template -class SimpleSync { +template class SimpleSync { public: - static constexpr unsigned int STR_LEN_MAX = str_len_max; - class NumberInterface { + class Interface { public: - time_t last_send; - char *key; - timedelta_t update_interval; + uint8_t type; + string key; + + std::function pack; + std::function unpack; + bool send_requested = true; - int value; - NumberInterface(SimpleSync &s, char *key, timedelta_t update_interval) - : key(key), update_interval(update_interval) { - s.number_interfaces.push_back(this); - } + time_t last_send; + + timedelta_t update_interval; + bool update_periodically; + + Interface(uint8_t type, string key, + std::function pack, + std::function unpack) + : type(type), key(key), pack(pack), unpack(unpack), update_periodically(false) {} + Interface(uint8_t type, string key, + std::function pack, + std::function unpack, + timedelta_t update_interval) + : Interface(type, key, pack, unpack), update_interval(update_interval), + update_periodically(true) {} }; - class StringInterface { - public: - time_t last_send; - char *key; - timedelta_t update_interval; - bool send_requested = true; - char value[str_len_max + 1]; - StringInterface(SimpleSync &s, char *key, timedelta_t update_interval) - : key(key), update_interval(update_interval) { - value[str_len_max] = 0x00; - s.string_interfaces.push_back(this); - } - }; + template static void Number(SimpleSync &sync, string key, int_t *value_ptr) { + sync.interfaces.push_back(std::make_unique( + 0x01, key, + [=](uint8_t *buf, unsigned int buf_size) -> int { /* pack */ + if (buf_size < sizeof(int) * 8 / 7) + return BUFFER_OVERFLOW; + return encode_varint(*value_ptr, buf); + }, + [=](uint8_t *buf, unsigned int buf_size) -> int { /* unpack */ + buf_size = 1 * buf_size; + return decode_varint(buf, *value_ptr); + })); + } - std::vector number_interfaces; - std::vector string_interfaces; + static void String(SimpleSync &sync, string key, string *value_ptr) { + sync.interfaces.push_back(std::make_unique( + 0x02, key, + [=](uint8_t *buf, unsigned int buf_size) -> int { /* pack */ + auto value_len = + 1 + strlen(value_ptr->c_str()); + if (buf_size < value_len) + return BUFFER_OVERFLOW; + memcpy(buf, value_ptr->c_str(), + value_len); + return value_len; + }, + [=](uint8_t *buf, unsigned int buf_size) -> int { /* unpack */ + auto strl = strlen((char *)buf) + 1; + if (strl <= buf_size) + return BUFFER_OVERFLOW; + value_ptr->assign((char *)buf); + return strl; + })); + } + + // int parse_number(uint8_t *buf, unsigned int buf_size, int* value){ + // return decode_varint(&buf[parsed], *value); + // } + + std::vector> interfaces; function write_pkg; - function number_update; - function string_update; + function &, char *, int)> interface_update; SimpleSync(function write_pkg, - function number_update, - function string_update) - : write_pkg(write_pkg), number_update(number_update), string_update(string_update) {} + function &, char *, int)> interface_update) + : write_pkg(write_pkg), interface_update(interface_update) {} + Interface &get_or_create_interface(uint8_t type, char *key) { + for (auto &i : interfaces) { + if (i->type == type && strcmp(i->key.c_str(), key) == 0) { + return *i; + } + } + } int parse_pkg(uint8_t *buf, unsigned int buf_size) { if (buf_size < 4) return CRC_MISSMATCH; uint16_t crc = calc_fletcher_checksum(buf, buf_size - 2); if (buf[--buf_size] != (crc & 0xFF) || (buf[--buf_size] != (crc >> 8))) return CRC_MISSMATCH; for (unsigned int parsed = 0; parsed < buf_size;) { - switch (buf[parsed]) { + uint8_t type = buf[parsed]; + switch (type) { case 0x00: { - for (auto ni : number_interfaces) ni->send_requested = true; - for (auto ni : string_interfaces) ni->send_requested = true; - } break; - case 0x01: { - char *key = (char *)&buf[parsed + 1]; - parsed += 1 + strlen(key) + 1; - int value; - parsed += decode_varint(&buf[parsed], value); - NumberInterface *ni_ptr = nullptr; - for (auto ni : number_interfaces) { - if (strcmp(ni->key, key) == 0) { - ni_ptr = ni; - break; - } - } - if (number_update) { - number_update(ni_ptr, key, value); - } - if (ni_ptr) { - ni_ptr->value = value; - } + for (auto ni : interfaces) ni->send_requested = true; } break; + case 0x01: case 0x02: { char *key = (char *)&buf[parsed + 1]; parsed += 1 + strlen(key) + 1; - char *value = (char *)&buf[parsed]; - unsigned int strl = strlen(value) + 1; - parsed += strl; - StringInterface *stri_ptr = nullptr; - for (StringInterface *si : string_interfaces) { - if (strcmp(si->key, key) == 0) { - stri_ptr = si; - break; - } - } - if (string_update) { - string_update(stri_ptr, key, value); - } - if (stri_ptr) { - memcpy(stri_ptr->value, value, str_len_max > strl ? strl : str_len_max); + Interface &ni = get_or_create_interface(type, key); + unsigned int unpacked_bytes = ni.unpack(buf + parsed, buf_size - parsed); + if (unpacked_bytes >= 0) { + parsed += unpacked_bytes; + } else { // ERROR -> return + return unpacked_bytes; } } break; default: @@ -239,11 +256,11 @@ class SimpleSync { void update(time_t time) { uint8_t buf[BUF_SIZE]; unsigned int buf_len_used = 0; - for (auto ni : number_interfaces) { + for (auto& ni : interfaces) { if (ni->send_requested || - (ni->last_send > time || ni->last_send <= time - ni->update_interval)) { - unsigned int strl = strlen(ni->key) + 1; - unsigned int buf_len_needed = 1 + strl + 8 * sizeof(int) / 7; + (ni->update_periodically && (ni->last_send > time || ni->last_send <= time - ni->update_interval))) { + unsigned int strl = strlen(ni->key.c_str()) + 1; + unsigned int buf_len_needed = 1 + strl + 32; // TODO get real pack size (not always 32) buf_len_needed += buf_len_needed / 0xFF + 3 + 2; // COBS overhead if (BUF_SIZE < buf_len_needed) continue; // Error: update to large, skip interface if (BUF_SIZE < buf_len_used + buf_len_needed) { @@ -256,39 +273,12 @@ class SimpleSync { write_pkg(cobs_buf, cobs_buf_needed); buf_len_used = 0; } - buf[buf_len_used++] = 0x01; - memcpy((char *)&buf[buf_len_used], ni->key, strl); - buf_len_used += strl; - buf_len_used += encode_varint(ni->value, &buf[buf_len_used]); - ni->last_send = time; - ni->send_requested = false; - } - } - for (auto ni : string_interfaces) { - if (ni->send_requested || - (ni->last_send > time || ni->last_send <= time - ni->update_interval)) { - unsigned int strl = strlen(ni->key) + 1; - unsigned int strl_value = strlen(ni->value) + 1; - unsigned int buf_len_needed = 1 + strl + strl_value; - buf_len_needed += buf_len_needed / 0xFF + 3 + 2; // COBS overhead - if (BUF_SIZE < buf_len_needed) continue; // Error: update to large, skip interface - if (BUF_SIZE < buf_len_used + buf_len_needed + 2) { - uint8_t cobs_buf[BUF_SIZE]; - uint16_t crc = calc_fletcher_checksum(buf, buf_len_used); - buf[buf_len_used++] = crc >> 8; - buf[buf_len_used++] = crc & 0xFF; - unsigned int cobs_buf_needed = - cobs_encode(buf, buf_len_used, cobs_buf, BUF_SIZE); - write_pkg(cobs_buf, cobs_buf_needed); - buf_len_used = 0; - } - buf[buf_len_used++] = 0x02; - memcpy((char *)&buf[buf_len_used], ni->key, strl); - buf_len_used += strl; - memcpy((char *)&buf[buf_len_used], ni->value, strl_value); - buf_len_used += strl_value; + buf[buf_len_used++] = ni->type; + memcpy((char *)&buf[buf_len_used], ni->key.c_str(), strl); + ni->pack(&buf[buf_len_used], BUF_SIZE - buf_len_used); ni->last_send = time; ni->send_requested = false; + } } if (buf_len_used == 0) return; @@ -350,20 +340,6 @@ class SimpleSync { return 0; } - NumberInterface *get_number_if(const char *const key) const { - for (const auto ni : number_interfaces) { - if (strcmp(ni->key, key) == 0) return ni; - } - return nullptr; - } - - StringInterface *get_string_if(const char *const key) const { - for (const auto ni : string_interfaces) { - if (strcmp(ni->key, key) == 0) return ni; - } - return nullptr; - } - #ifdef ARDUINO SimpleSync(Print *ostream, function number_update, function string_update)