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.
 
 
 
 
 
 

169 lines
3.8 KiB

/*
WEBSOCKET MODULE
Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#pragma once
#include "espurna.h"
#include <IPAddress.h>
#include <cstdint>
#include <memory>
#include <vector>
constexpr const size_t WS_DEBUG_MSG_BUFFER = 8;
// -----------------------------------------------------------------------------
// WS authentication
// -----------------------------------------------------------------------------
struct ws_ticket_t {
IPAddress ip;
unsigned long timestamp = 0;
};
// -----------------------------------------------------------------------------
// WS callbacks
// -----------------------------------------------------------------------------
struct ws_counter_t {
ws_counter_t() : current(0), start(0), stop(0) {}
ws_counter_t(uint32_t start, uint32_t stop) :
current(start), start(start), stop(stop) {}
void reset() {
current = start;
}
void next() {
if (current < stop) {
++current;
}
}
bool done() {
return (current >= stop);
}
uint32_t current;
uint32_t start;
uint32_t stop;
};
struct ws_data_t {
enum mode_t {
SEQUENCE,
ALL
};
ws_data_t(const ws_on_send_callback_f& cb) :
storage(new ws_on_send_callback_list_t {cb}),
client_id(0),
mode(ALL),
callbacks(*storage.get()),
counter(0, 1)
{}
ws_data_t(uint32_t client_id, const ws_on_send_callback_f& cb) :
storage(new ws_on_send_callback_list_t {cb}),
client_id(client_id),
mode(ALL),
callbacks(*storage.get()),
counter(0, 1)
{}
ws_data_t(const uint32_t client_id, ws_on_send_callback_list_t&& callbacks, mode_t mode = SEQUENCE) :
storage(new ws_on_send_callback_list_t(std::move(callbacks))),
client_id(client_id),
mode(mode),
callbacks(*storage.get()),
counter(0, (storage.get())->size())
{}
ws_data_t(const uint32_t client_id, const ws_on_send_callback_list_t& callbacks, mode_t mode = SEQUENCE) :
client_id(client_id),
mode(mode),
callbacks(callbacks),
counter(0, callbacks.size())
{}
bool done() {
return counter.done();
}
void sendAll(JsonObject& root) {
while (!counter.done()) counter.next();
for (auto& callback : callbacks) {
callback(root);
}
}
void sendCurrent(JsonObject& root) {
callbacks[counter.current](root);
counter.next();
}
void send(JsonObject& root) {
switch (mode) {
case SEQUENCE: sendCurrent(root); break;
case ALL: sendAll(root); break;
}
}
std::unique_ptr<ws_on_send_callback_list_t> storage;
const uint32_t client_id;
const mode_t mode;
const ws_on_send_callback_list_t& callbacks;
ws_counter_t counter;
};
// -----------------------------------------------------------------------------
// Debug
// -----------------------------------------------------------------------------
using ws_debug_msg_t = std::pair<String, String>;
struct ws_debug_t {
ws_debug_t(size_t capacity) :
flush(false),
current(0),
capacity(capacity)
{
messages.reserve(capacity);
}
void clear() {
messages.clear();
current = 0;
flush = false;
}
void add(const char* prefix, const char* message) {
if (current >= capacity) {
flush = true;
send(wsConnected());
}
messages.emplace(messages.begin() + current, prefix, message);
flush = true;
++current;
}
void send(const bool connected);
bool flush;
size_t current;
const size_t capacity;
std::vector<ws_debug_msg_t> messages;
};