Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

177 lines
4.3 KiB

/*
Part of the WEBSOCKET MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
Copyright (C) 2019 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
*/
#pragma once
#include "espurna.h"
#include "ws.h"
#include <IPAddress.h>
#include <cstdint>
#include <memory>
#include <vector>
// -----------------------------------------------------------------------------
// WS authentication
// -----------------------------------------------------------------------------
struct WsTicket {
IPAddress ip;
unsigned long timestamp = 0;
};
// -----------------------------------------------------------------------------
// WS callbacks
// -----------------------------------------------------------------------------
// The idea here is to bind either:
// - constant 'callbacks' list as reference, which was registered via wsRegister()
// - in-place callback / callbacks that will be moved inside this container
struct WsPostponedCallbacks {
public:
enum class Mode {
Sequence,
All
};
WsPostponedCallbacks(uint32_t client_id, ws_on_send_callback_f&& cb) :
client_id(client_id),
timestamp(ESP.getCycleCount()),
_storage(new ws_on_send_callback_list_t {std::move(cb)}),
_callbacks(*_storage.get()),
_current(_callbacks.begin()),
_mode(Mode::All)
{}
WsPostponedCallbacks(uint32_t client_id, const ws_on_send_callback_f& cb) :
client_id(client_id),
timestamp(ESP.getCycleCount()),
_storage(new ws_on_send_callback_list_t {cb}),
_callbacks(*_storage.get()),
_current(_callbacks.begin()),
_mode(Mode::All)
{}
template <typename T>
explicit WsPostponedCallbacks(T&& cb) :
WsPostponedCallbacks(0, std::forward<T>(cb))
{}
WsPostponedCallbacks(const uint32_t client_id, const ws_on_send_callback_list_t& cbs, Mode mode = Mode::Sequence) :
client_id(client_id),
timestamp(ESP.getCycleCount()),
_callbacks(cbs),
_current(_callbacks.begin()),
_mode(mode)
{}
WsPostponedCallbacks(const uint32_t client_id, ws_on_send_callback_list_t&& cbs, Mode mode = Mode::All) :
client_id(client_id),
timestamp(ESP.getCycleCount()),
_storage(new ws_on_send_callback_list_t(std::move(cbs))),
_callbacks(*_storage.get()),
_current(_callbacks.begin()),
_mode(mode)
{}
bool done() {
return _current == _callbacks.end();
}
void sendAll(JsonObject& root) {
_current = _callbacks.end();
for (auto& callback : _callbacks) {
callback(root);
}
}
void sendCurrent(JsonObject& root) {
if (_current == _callbacks.end()) return;
(*_current)(root);
++_current;
}
void send(JsonObject& root) {
switch (_mode) {
case Mode::Sequence:
sendCurrent(root);
break;
case Mode::All:
sendAll(root);
break;
}
}
const uint32_t client_id;
const decltype(ESP.getCycleCount()) timestamp;
private:
std::unique_ptr<ws_on_send_callback_list_t> _storage;
const ws_on_send_callback_list_t& _callbacks;
ws_on_send_callback_list_t::const_iterator _current;
const Mode _mode;
};
// -----------------------------------------------------------------------------
// Debug
// -----------------------------------------------------------------------------
struct WsDebug {
using Message = std::pair<String, String>;
using MsgList = std::vector<Message>;
WsDebug(size_t capacity) :
_flush(false),
_current(0),
_capacity(capacity)
{
_messages.reserve(_capacity);
}
void clear() {
_messages.clear();
_current = 0;
_flush = false;
}
template <typename T = Message>
void add(T&& message) {
if (_current >= _capacity) {
_flush = true;
send(wsConnected());
}
_messages.emplace(_messages.begin() + _current, std::forward<T>(message));
_flush = true;
++_current;
}
void add(const char* prefix, const char* message) {
add(std::move(std::make_pair(prefix, message)));
}
void send(bool connected);
private:
bool _flush;
size_t _current;
const size_t _capacity;
MsgList _messages;
};