Initial commit with refactored sources from goe charger source code

This commit is contained in:
2021-01-02 18:55:44 +01:00
parent 0242257b9b
commit 7bcffb0253
8 changed files with 572 additions and 0 deletions

36
cleanuphelper.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
// system includes
#include <utility>
#include <optional>
namespace espcpputils {
template<typename T>
class CleanupHelper
{
public:
CleanupHelper(T && cleanup) :
m_cleanup{std::move(cleanup)}
{}
~CleanupHelper()
{
if (m_cleanup)
(*m_cleanup)();
}
void disarm()
{
m_cleanup = std::nullopt;
}
private:
std::optional<T> m_cleanup;
};
template<typename T>
CleanupHelper<T> makeCleanupHelper(T && cleanup)
{
return CleanupHelper<T>(std::move(cleanup));
}
} // namespace espcpputils

99
delayedconstruction.h Normal file
View File

@ -0,0 +1,99 @@
#pragma once
// system includes
#include <cassert>
#include <type_traits>
#include <utility>
// local includes
#include "esputils.h"
namespace espcpputils {
template<typename T>
class DelayedConstruction
{
ESP_DISABLE_COPY_MOVE(DelayedConstruction)
public:
DelayedConstruction() = default;
~DelayedConstruction()
{
if (m_constructed)
destruct();
}
template<typename ...Targs>
void construct(Targs &&...args)
{
assert(!m_constructed);
new (&helper.value) T {std::forward<Targs>(args)...};
m_constructed = true;
}
void destruct()
{
assert(m_constructed);
helper.value.~T();
m_constructed = false;
}
T &get()
{
assert(m_constructed);
return helper.value;
}
const T &get() const
{
assert(m_constructed);
return helper.value;
}
T *operator->()
{
assert(m_constructed);
return &helper.value;
}
const T *operator->() const
{
assert(m_constructed);
return &helper.value;
}
T &operator*()
{
assert(m_constructed);
return helper.value;
}
const T &operator*() const
{
assert(m_constructed);
return helper.value;
}
//! allows for getting the address before the object has been constructed
T &getUnsafe()
{
return helper.value;
}
//! allows for getting the address before the object has been constructed
const T &getUnsafe() const
{
return helper.value;
}
bool constructed() const { return m_constructed; }
private:
bool m_constructed{};
union Helper
{
Helper() {}
~Helper() {}
T value;
} helper;
};
} // namespace espcpputils

114
espflags.h Normal file
View File

@ -0,0 +1,114 @@
#pragma once
// system includes
#include <type_traits>
#include <cstddef>
#include <utility>
#include <cstdint>
namespace espcpputils {
class EspFlag
{
using uint = unsigned int;
using ushort = unsigned short;
int i;
public:
constexpr inline EspFlag(int value) noexcept : i(value) {}
constexpr inline operator int() const noexcept { return i; }
constexpr inline EspFlag(uint value) noexcept : i(int(value)) {}
constexpr inline EspFlag(short value) noexcept : i(int(value)) {}
constexpr inline EspFlag(ushort value) noexcept : i(int(uint(value))) {}
constexpr inline operator uint() const noexcept { return uint(i); }
};
template<typename Enum>
class EspFlags
{
static_assert((sizeof(Enum) <= sizeof(int)),
"EspFlags uses an int as storage, so an enum with underlying "
"long long will overflow.");
static_assert((std::is_enum<Enum>::value), "EspFlags is only usable on enumeration types.");
using uint = unsigned int;
using ushort = unsigned short;
public:
typedef typename std::conditional<
std::is_unsigned<typename std::underlying_type<Enum>::type>::value,
unsigned int,
signed int
>::type Int;
typedef Enum enum_type;
constexpr inline EspFlags() noexcept : i(0) {}
constexpr inline EspFlags(Enum flags) noexcept : i(Int(flags)) {}
constexpr inline EspFlags(EspFlag flag) noexcept : i(flag) {}
constexpr inline EspFlags(std::initializer_list<Enum> flags) noexcept
: i(initializer_list_helper(flags.begin(), flags.end())) {}
constexpr inline EspFlags &operator&=(int mask) noexcept { i &= mask; return *this; }
constexpr inline EspFlags &operator&=(uint mask) noexcept { i &= mask; return *this; }
constexpr inline EspFlags &operator&=(Enum mask) noexcept { i &= Int(mask); return *this; }
constexpr inline EspFlags &operator|=(EspFlags other) noexcept { i |= other.i; return *this; }
constexpr inline EspFlags &operator|=(Enum other) noexcept { i |= Int(other); return *this; }
constexpr inline EspFlags &operator^=(EspFlags other) noexcept { i ^= other.i; return *this; }
constexpr inline EspFlags &operator^=(Enum other) noexcept { i ^= Int(other); return *this; }
constexpr inline operator Int() const noexcept { return i; }
constexpr inline EspFlags operator|(EspFlags other) const noexcept { return EspFlags(EspFlag(i | other.i)); }
constexpr inline EspFlags operator|(Enum other) const noexcept { return EspFlags(EspFlag(i | Int(other))); }
constexpr inline EspFlags operator^(EspFlags other) const noexcept { return EspFlags(EspFlag(i ^ other.i)); }
constexpr inline EspFlags operator^(Enum other) const noexcept { return EspFlags(EspFlag(i ^ Int(other))); }
constexpr inline EspFlags operator&(int mask) const noexcept { return EspFlags(EspFlag(i & mask)); }
constexpr inline EspFlags operator&(uint mask) const noexcept { return EspFlags(EspFlag(i & mask)); }
constexpr inline EspFlags operator&(Enum other) const noexcept { return EspFlags(EspFlag(i & Int(other))); }
constexpr inline EspFlags operator~() const noexcept { return EspFlags(EspFlag(~i)); }
constexpr inline bool operator!() const noexcept { return !i; }
constexpr inline bool testFlag(Enum flag) const noexcept { return (i & Int(flag)) == Int(flag) && (Int(flag) != 0 || i == Int(flag) ); }
constexpr inline EspFlags &setFlag(Enum flag, bool on = true) noexcept
{
return on ? (*this |= flag) : (*this &= ~Int(flag));
}
private:
constexpr static inline Int initializer_list_helper(typename std::initializer_list<Enum>::const_iterator it,
typename std::initializer_list<Enum>::const_iterator end)
noexcept
{
return (it == end ? Int(0) : (Int(*it) | initializer_list_helper(it + 1, end)));
}
Int i;
};
class EspIncompatibleFlag
{
int i;
public:
constexpr inline explicit EspIncompatibleFlag(int i) noexcept;
constexpr inline operator int() const noexcept { return i; }
};
constexpr inline EspIncompatibleFlag::EspIncompatibleFlag(int value) noexcept : i(value) {}
} // namespace espcpputils
#define ESP_DECLARE_FLAGS(Flags, Enum)\
typedef ::espcpputils::EspFlags<Enum> Flags;
#define ESP_DECLARE_INCOMPATIBLE_FLAGS(Flags) \
constexpr inline ::espcpputils::EspIncompatibleFlag operator|(Flags::enum_type f1, int f2) noexcept \
{ return ::espcpputils::EspIncompatibleFlag(int(f1) | f2); }
#define ESP_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
constexpr inline ::espcpputils::EspFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) noexcept \
{ return ::espcpputils::EspFlags<Flags::enum_type>(f1) | f2; } \
constexpr inline ::espcpputils::EspFlags<Flags::enum_type> operator|(Flags::enum_type f1, ::espcpputils::EspFlags<Flags::enum_type> f2) noexcept \
{ return f2 | f1; } ESP_DECLARE_INCOMPATIBLE_FLAGS(Flags)

111
esputils.h Normal file
View File

@ -0,0 +1,111 @@
#pragma once
// system includes
#include <algorithm>
#include <cstdint>
#include <functional>
#include <vector>
/*
Avoid "unused parameter" warnings
*/
#define ESP_UNUSED(x) (void)x;
/* These two macros make it possible to turn the builtin line expander into a
* string literal. */
#define ESP_STRINGIFY2(x) #x
#define ESP_STRINGIFY(x) ESP_STRINGIFY2(x)
/*
Some classes do not permit copies to be made of an object. These
classes contains a private copy constructor and assignment
operator to disable copying (the compiler gives an error message).
*/
#define ESP_DISABLE_COPY(Class) \
Class(const Class &) = delete;\
Class &operator=(const Class &) = delete;
#define ESP_DISABLE_MOVE(Class) \
Class(Class &&) = delete; \
Class &operator=(Class &&) = delete;
#define ESP_DISABLE_COPY_MOVE(Class) \
ESP_DISABLE_COPY(Class) \
ESP_DISABLE_MOVE(Class)
/* These two macros make it possible to define a typesafe enum with parse and
* toString methods */
#define DECLARE_TYPESAFE_ENUM_HELPER1(name) name,
#define DECLARE_TYPESAFE_ENUM_HELPER2(name) case TheEnum::name: return #name;
#define DECLARE_TYPESAFE_ENUM_HELPER3(name) else if (str == ESP_STRINGIFY(name)) return TheEnum::name;
#define DECLARE_TYPESAFE_ENUM(Name, Derivation, Values) \
enum class Name Derivation \
{ \
Values(DECLARE_TYPESAFE_ENUM_HELPER1) \
}; \
namespace { \
template<typename T> \
T toString(Name value) \
{ \
switch (value) \
{ \
using TheEnum = Name; \
Values(DECLARE_TYPESAFE_ENUM_HELPER2) \
} \
return T{"Unknown " #Name "("} + int(value) + ')'; \
} \
template<typename T> \
std::optional<Name> parse##Name(const T &str) \
{ \
using TheEnum = Name; \
if (false) {} \
Values(DECLARE_TYPESAFE_ENUM_HELPER3) \
return std::nullopt; \
} \
} // namespace
namespace espcpputils {
template<class T>
constexpr const T& clamp( const T& v, const T& lo, const T& hi )
{
// assert( !(hi < lo) );
return (v < lo) ? lo : (hi < v) ? hi : v;
}
template<typename T>
T mapValue(T x, T in_min, T in_max, T out_min, T out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
template<typename... T>
class Signal
{
public:
using Slot = std::function<void(T...)>;
Signal &operator+=(Slot &&slot)
{
m_slots.emplace_back(std::move(slot));
return *this;
}
Signal &operator+=(const Slot &slot)
{
m_slots.emplace_back(slot);
return *this;
}
template<typename ...Targs>
void operator()(Targs && ...args) const
{
for (const auto &slot : m_slots)
slot(std::forward<Targs>(args)...);
}
private:
std::vector<Slot> m_slots;
};
} // namespace espcpputils

36
event_group.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
// espressif includes
#include <freertos/FreeRTOS.h>
#include <freertos/event_groups.h>
// local includes
#include "esputils.h"
namespace espcpputils {
class event_group
{
ESP_DISABLE_COPY_MOVE(event_group)
public:
event_group() :
handle{xEventGroupCreate()}
{}
~event_group() { if (handle) vEventGroupDelete(handle); }
EventBits_t waitBits(const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait)
{ return xEventGroupWaitBits(handle, uxBitsToWaitFor, xClearOnExit, xWaitForAllBits, xTicksToWait); }
EventBits_t clearBits(const EventBits_t uxBitsToClear) { return xEventGroupClearBits(handle, uxBitsToClear); }
EventBits_t setBits(const EventBits_t uxBitsToSet) { return xEventGroupSetBits(handle, uxBitsToSet); }
EventBits_t groupSync(const EventBits_t uxBitsToSet, const EventBits_t uxBitsToWaitFor, TickType_t xTicksToWait)
{ return xEventGroupSync(handle, uxBitsToSet, uxBitsToWaitFor, xTicksToWait); }
EventBits_t getBits() const { return xEventGroupClearBits(handle, 0); }
const EventGroupHandle_t handle;
};
} // namespace espcpputils

77
http_client.h Normal file
View File

@ -0,0 +1,77 @@
#pragma once
// espressif includes
#include <esp_http_client.h>
// local includes
#include "esputils.h"
namespace espcpputils {
class http_client
{
ESP_DISABLE_COPY_MOVE(http_client)
public:
http_client(const esp_http_client_config_t *config) :
handle{esp_http_client_init(config)}
{}
~http_client() { if (handle) esp_http_client_cleanup(handle); }
esp_err_t perform() { return esp_http_client_perform(handle); }
esp_err_t set_url(const char *url) { return esp_http_client_set_url(handle, url); }
esp_err_t set_post_field(const char *data, int len) { return esp_http_client_set_post_field(handle, data, len); }
int get_post_field(char **data) { return esp_http_client_get_post_field(handle, data); }
esp_err_t set_header(const char *key, const char *value) { return esp_http_client_set_header(handle, key, value); }
esp_err_t get_header(const char *key, char **value) { return esp_http_client_get_header(handle, key, value); }
esp_err_t get_username(char **value) { return esp_http_client_get_username(handle, value); }
esp_err_t set_username(const char *username) { return esp_http_client_set_username(handle, username); }
esp_err_t get_password(char **value) { return esp_http_client_get_password(handle, value); }
esp_err_t set_password(char *password) { return esp_http_client_set_password(handle, password); }
esp_err_t set_method(esp_http_client_method_t method) { return esp_http_client_set_method(handle, method); }
esp_err_t delete_header(const char *key) { return esp_http_client_delete_header(handle, key); }
esp_err_t open(int write_len) { return esp_http_client_open(handle, write_len); }
int write(const char *buffer, int len) { return esp_http_client_write(handle, buffer, len); }
int fetch_headers() { return esp_http_client_fetch_headers(handle); }
bool is_chunked_response() const { return esp_http_client_is_chunked_response(handle); }
int read(char *buffer, int len) { return esp_http_client_read(handle, buffer, len); }
int get_status_code() const { return esp_http_client_get_status_code(handle); }
int get_content_length() const { return esp_http_client_get_content_length(handle); }
esp_err_t close() { return esp_http_client_close(handle); }
esp_http_client_transport_t get_transport_type() const { return esp_http_client_get_transport_type(handle); }
esp_err_t set_redirection() { return esp_http_client_set_redirection(handle); }
void add_auth() { return esp_http_client_add_auth(handle); }
bool is_complete_data_received() const { return esp_http_client_is_complete_data_received(handle); }
static esp_http_client_config_t zeroInitializedConfig()
{
return esp_http_client_config_t {
.url = {},
.host = {},
.port = {},
.username = {},
.password = {},
.auth_type = {},
.path = {},
.query = {},
.cert_pem = {},
.client_cert_pem = {},
.client_key_pem = {},
.method = {},
.timeout_ms = {},
.disable_auto_redirect = {},
.max_redirection_count = {},
.event_handler = {},
.transport_type = {},
.buffer_size = {},
.buffer_size_tx = {},
.user_data = {},
.is_async = {},
.use_global_ca_store = {},
.skip_cert_common_name_check = {}
};
}
const esp_http_client_handle_t handle;
};
} // namespace espcpputils

36
websocket_client.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
// espressif includes
#include <esp_websocket_client.h>
// local includes
#include "esputils.h"
namespace espcpputils {
class websocket_client
{
ESP_DISABLE_COPY_MOVE(websocket_client)
public:
websocket_client(const esp_websocket_client_config_t &config) :
handle{esp_websocket_client_init(&config)}
{
}
~websocket_client() { if (handle) esp_websocket_client_destroy(handle); }
esp_err_t set_uri (const char *uri) { return esp_websocket_client_set_uri (handle, uri); }
esp_err_t start () { return esp_websocket_client_start (handle); }
esp_err_t stop () { return esp_websocket_client_stop (handle); }
int send (const char *data, int len, TickType_t timeout) { return esp_websocket_client_send (handle, data, len, timeout); }
int send_bin (const char *data, int len, TickType_t timeout) { return esp_websocket_client_send_bin (handle, data, len, timeout); }
int send_text (const char *data, int len, TickType_t timeout) { return esp_websocket_client_send_text (handle, data, len, timeout); }
//esp_err_t close (TickType_t timeout) { return esp_websocket_client_close (handle, timeout); }
//esp_err_t close_with_code(int code, const char *data, int len, TickType_t timeout) { return esp_websocket_client_close_with_code(handle, code, data, len, timeout); }
bool is_connected () const { return esp_websocket_client_is_connected (handle); }
esp_err_t register_events(esp_websocket_event_id_t event, esp_event_handler_t event_handler, void *event_handler_arg)
{ return esp_websocket_register_events(handle, event, event_handler, event_handler_arg); }
const esp_websocket_client_handle_t handle;
};
} // namespace espcpputils

63
wifiutils.h Normal file
View File

@ -0,0 +1,63 @@
#pragma once
// Arduino includes
#include <WiFi.h>
#include <WiFiType.h>
namespace espcpputils {
namespace {
template<typename T>
T scanResultToString(int16_t result)
{
if (result < 0)
{
switch (result)
{
case WIFI_SCAN_RUNNING: return "WIFI_SCAN_RUNNING";
case WIFI_SCAN_FAILED: return "WIFI_SCAN_FAILED";
}
return T{"Failed ("} + result + ')';
}
return T{"Finished ("} + result + ')';
}
template<typename T>
T toString(wifi_auth_mode_t encryptionType)
{
switch (encryptionType)
{
case WIFI_AUTH_OPEN: return "WIFI_AUTH_OPEN";
case WIFI_AUTH_WEP: return "WIFI_AUTH_WEP";
case WIFI_AUTH_WPA_PSK: return "WIFI_AUTH_WPA_PSK";
case WIFI_AUTH_WPA2_PSK: return "WIFI_AUTH_WPA2_PSK";
case WIFI_AUTH_WPA_WPA2_PSK: return "WIFI_AUTH_WPA_WPA2_PSK";
case WIFI_AUTH_WPA2_ENTERPRISE: return "WIFI_AUTH_WPA2_ENTERPRISE";
case WIFI_AUTH_WPA3_PSK: return "WIFI_AUTH_WPA3_PSK";
case WIFI_AUTH_WPA2_WPA3_PSK: return "WIFI_AUTH_WPA2_WPA3_PSK";
case WIFI_AUTH_MAX: return "WIFI_AUTH_MAX";
}
return T{"Unknown wifi_auth_mode_t("} + encryptionType + ')';
}
template<typename T>
T toString(wl_status_t status)
{
switch (status)
{
case WL_NO_SHIELD: return "WL_NO_SHIELD";
case WL_IDLE_STATUS: return "WL_IDLE_STATUS";
case WL_NO_SSID_AVAIL: return "WL_NO_SSID_AVAIL";
case WL_SCAN_COMPLETED: return "WL_SCAN_COMPLETED";
case WL_CONNECTED: return "WL_CONNECTED";
case WL_CONNECT_FAILED: return "WL_CONNECT_FAILED";
case WL_CONNECTION_LOST: return "WL_CONNECTION_LOST";
case WL_DISCONNECTED: return "WL_DISCONNECTED";
}
return T{"Unknown wl_status_t("} + int(status) + ')';
}
} // namespace
} // namespace espcpputils