mirror of
https://github.com/xoseperez/espurna.git
synced 2026-03-14 12:17:11 +01:00
274 lines
6.3 KiB
C++
274 lines
6.3 KiB
C++
/*
|
|
|
|
Part of the WEBSOCKET MODULE
|
|
|
|
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
|
|
Copyright (C) 2019-2021 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
|
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
// Generic payload for indexed aka enumerable entries
|
|
// For the specific root container, add 'name'ed key and the function that will generate entry from index / id
|
|
// Each key is appended to the 'schema' list that will be used by the webui to know the actual settings key
|
|
//
|
|
// For example
|
|
// ```
|
|
// {
|
|
// name:
|
|
// {
|
|
// schema: ["one", "two", "three", "four"],
|
|
// values: [
|
|
// [1,2,3,4],
|
|
// [5,6,7,8],
|
|
// [9,0,1,2],
|
|
// [3,4,5,6]
|
|
// ]
|
|
// }
|
|
// }
|
|
// ```
|
|
//
|
|
// On the webui side, these become
|
|
// ```
|
|
// one0 => 1, two0 => 2, three0 => 3, four0 => 4
|
|
// one1 => 5, two1 => 6, three1 => 7, four1 => 8
|
|
// ...etc...
|
|
// ```
|
|
// Where each row in values is the specific index, and the key string is taken from the schema list
|
|
// Obviously, number of elements is always expected to match
|
|
|
|
#include <ArduinoJson.h>
|
|
|
|
#include "system_time.h"
|
|
#include "settings.h"
|
|
|
|
namespace espurna {
|
|
namespace web {
|
|
namespace ws {
|
|
|
|
// generic way to set up iterable payload with a schema
|
|
struct EnumerablePayload {
|
|
using Check = bool(*)(size_t);
|
|
using Generator = void(*)(JsonArray&, size_t);
|
|
|
|
struct Pair {
|
|
StringView name;
|
|
Generator generate;
|
|
};
|
|
|
|
using Pairs = std::initializer_list<Pair>;
|
|
|
|
EnumerablePayload(JsonObject& root, StringView name);
|
|
|
|
void operator()(StringView name, settings::Iota iota, Check, Pairs&&);
|
|
void operator()(StringView name, size_t iota_end, Pairs&& pairs) {
|
|
(*this)(name, settings::Iota { iota_end }, nullptr, std::move(pairs));
|
|
}
|
|
|
|
JsonObject& root() {
|
|
return _root;
|
|
}
|
|
|
|
private:
|
|
JsonObject& _root;
|
|
};
|
|
|
|
// payload generator for IndexedSettings
|
|
struct EnumerableConfig {
|
|
using Check = bool(*)(size_t);
|
|
using Setting = const settings::query::IndexedSetting;
|
|
|
|
using SourceFunc = Setting::ValueFunc;
|
|
using TargetFunc = void (*)(JsonArray&, size_t);
|
|
|
|
EnumerableConfig(JsonObject& root, StringView name);
|
|
|
|
void operator()(StringView name, settings::Iota iota, Check check, Setting* begin, Setting* end);
|
|
void operator()(StringView name, settings::Iota iota, Setting* begin, Setting* end) {
|
|
(*this)(name, iota, nullptr, begin, end);
|
|
}
|
|
|
|
template <typename T>
|
|
void operator()(StringView name, settings::Iota iota, T&& settings) {
|
|
(*this)(name, iota, std::begin(settings), std::end(settings));
|
|
}
|
|
|
|
template <typename T>
|
|
void operator()(StringView name, size_t iota_end, T&& settings) {
|
|
(*this)(name, settings::Iota{iota_end}, std::forward<T>(settings));
|
|
}
|
|
|
|
template <typename T>
|
|
void operator()(StringView name, size_t iota_end, Check check, T&& settings) {
|
|
(*this)(name, settings::Iota{iota_end}, check, std::begin(settings), std::end(settings));
|
|
}
|
|
|
|
JsonObject& root() {
|
|
return _root;
|
|
}
|
|
|
|
void replacement(SourceFunc, TargetFunc);
|
|
|
|
private:
|
|
struct Replacement {
|
|
SourceFunc source;
|
|
TargetFunc target;
|
|
};
|
|
|
|
|
|
std::vector<Replacement> _replacements;
|
|
JsonObject& _root;
|
|
};
|
|
|
|
struct EnumerableTypes {
|
|
template <typename T>
|
|
using Enumeration = settings::options::Enumeration<T>;
|
|
|
|
EnumerableTypes(JsonObject& root, StringView name);
|
|
|
|
template <typename T>
|
|
void operator()(const Enumeration<T>* begin, const Enumeration<T>* end) {
|
|
for (auto it = begin; it != end; ++it) {
|
|
(*this)((*it).numeric(), (*it).string());
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void operator()(const T& other) {
|
|
(*this)(std::begin(other), std::end(other));
|
|
}
|
|
|
|
void operator()(int, StringView);
|
|
|
|
private:
|
|
JsonArray& _root;
|
|
};
|
|
|
|
struct PostponedDebug;
|
|
|
|
struct PostponedPayload {
|
|
static constexpr size_t BufferHint = size_t{ JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(1) };
|
|
static constexpr size_t CountMax { 8 };
|
|
|
|
struct Flag {
|
|
explicit Flag(PostponedPayload&);
|
|
~Flag();
|
|
|
|
Flag(const Flag&) = delete;
|
|
Flag& operator=(const Flag&) = delete;
|
|
|
|
Flag(Flag&&) = delete;
|
|
Flag& operator=(Flag&&) = delete;
|
|
|
|
const char* data() const {
|
|
return _ref._data.c_str();
|
|
}
|
|
|
|
bool pending() const {
|
|
return _ref.pending();
|
|
}
|
|
|
|
private:
|
|
PostponedPayload& _ref;
|
|
};
|
|
|
|
PostponedPayload();
|
|
explicit PostponedPayload(uint32_t id) :
|
|
_id(id)
|
|
{}
|
|
|
|
bool pending() const {
|
|
return _pending;
|
|
}
|
|
|
|
bool post(bool connected);
|
|
bool post();
|
|
|
|
void buffer(const char*, size_t);
|
|
bool connected() const;
|
|
|
|
std::shared_ptr<Flag> make_flag();
|
|
|
|
private:
|
|
friend Flag;
|
|
friend PostponedDebug;
|
|
|
|
void buffer_impl(StringView);
|
|
void buffer_impl(const char*, size_t);
|
|
|
|
size_t _count{};
|
|
|
|
String _data;
|
|
bool _pending { false };
|
|
|
|
uint32_t _id{};
|
|
};
|
|
|
|
struct PostponedDebug : public PostponedPayload {
|
|
void buffer(const DebugPrefix&, const char*, size_t);
|
|
};
|
|
|
|
struct InplaceLog;
|
|
|
|
struct InplacePayload {
|
|
static constexpr size_t BufferHint = size_t{ JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(1) };
|
|
|
|
using Clock = espurna::time::CoreClock;
|
|
using Send = std::function<void(JsonObject&, String&)>;
|
|
|
|
static constexpr size_t CountMax { 8 };
|
|
|
|
static constexpr auto DefaultTimeout = duration::Seconds{ 2 };
|
|
static constexpr auto DefaultWait = duration::Milliseconds{ 100 };
|
|
|
|
InplacePayload() = delete;
|
|
InplacePayload(JsonObject& root, uint32_t id);
|
|
|
|
void reset();
|
|
|
|
bool connected() const;
|
|
bool can_send() const;
|
|
|
|
void write(const char*, size_t);
|
|
bool poll_send();
|
|
bool send();
|
|
|
|
void timeout(Clock::duration duration) {
|
|
_timeout = duration;
|
|
}
|
|
|
|
void wait_time(Clock::duration duration) {
|
|
_wait = duration;
|
|
}
|
|
|
|
private:
|
|
void write_impl(const char*, size_t);
|
|
void send_impl();
|
|
|
|
friend InplaceLog;
|
|
|
|
Clock::duration _timeout { DefaultTimeout };
|
|
Clock::duration _wait { DefaultWait };
|
|
|
|
String _data;
|
|
size_t _count{};
|
|
|
|
JsonObject& _root;
|
|
uint32_t _id;
|
|
};
|
|
|
|
struct InplaceLog : public InplacePayload {
|
|
InplaceLog(JsonObject&, uint32_t);
|
|
|
|
void write(const char* , size_t);
|
|
bool send();
|
|
|
|
private:
|
|
JsonArray& _log;
|
|
};
|
|
|
|
} // namespace ws
|
|
} // namespace web
|
|
} // namespace espurna
|