#pragma once #include #include #include #include #include "topic.hpp" #ifndef MAX_CID #define MAX_CID 4 #endif enum class MsgKind : uint8_t { Connect = 0, Disconnect = 1, Event = 2, Ping = 3, Pong = 4 }; template (Topic::COUNT)> class CommBase { using Bits = std::bitset; std::array subs_; portMUX_TYPE mux_ portMUX_INITIALIZER_UNLOCKED; static constexpr size_t idx(Topic t) { return static_cast(t); } template void encode(JsonDocument& d, const typename TopicTraits::Msg& m) { auto a = d.to(); a.add(static_cast(MsgKind::Event)); a.add(static_cast(T)); toJson(a.add(), m); } protected: virtual void send(size_t cid, const char* data, size_t len) = 0; public: void subscribe(Topic t, size_t cid) { portENTER_CRITICAL(&mux_); subs_[idx(t)].set(cid); portEXIT_CRITICAL(&mux_); } void unsubscribe(Topic t, size_t cid) { portENTER_CRITICAL(&mux_); subs_[idx(t)].reset(cid); portEXIT_CRITICAL(&mux_); } bool has(Topic t) const { return subs_[idx(t)].any(); } template void emit(const typename TopicTraits::Msg& m) { if (!has(T)) return; JsonDocument doc; encode(doc, m); String out; #if USE_MSGPACK serializeMsgPack(doc, out); #else serializeJson(doc, out); #endif auto& b = subs_[idx(T)]; for (size_t cid = 0; cid < MaxCid; ++cid) if (b.test(cid)) send(cid, out.c_str(), out.length()); } };