fwt_software/include/fgc/mock/NullControlChannel.h

77 lines
2.9 KiB
C++

#pragma once
#include "fgc/ChannelHistory.h"
#include "fgc/ChannelTopics.h"
#include "fgc/IControlChannel.h"
#include "fgc/Logger.h"
#include <string>
#include <utility>
#include <vector>
namespace fgc {
// No-op control channel for running without an MQTT broker. Publishes go
// nowhere, and no commands arrive unless a test inject()s one.
//
// It still records what it was asked to send, using the same topic and payload
// builders as the real channel, so the connectivity view works under --no-mqtt
// and shows exactly what would have gone out. Every entry is Delivery::Dropped,
// which is the truth: nothing was sent.
class NullControlChannel : public IControlChannel {
public:
explicit NullControlChannel(std::string tower = "") : tower_(std::move(tower)) {}
bool connect() override { return true; }
void disconnect() override {}
bool connected() const override { return true; }
void publishStatus(int code) override {
const std::string payload = std::to_string(code);
history_.noteStatus(payload);
LOG_TRACE_CAT(LogCat::Mqtt) << "PUB StatusCode " << code << " (null channel)";
drop(kTopicStatusCode, payload);
}
void publishCamEvent(const CamEvent& e) override {
LOG_TRACE_CAT(LogCat::Mqtt) << "PUB CamEvent cam=" << e.camera
<< " hdg=" << e.heading_decideg << " t=" << e.timestamp_ms
<< " (null channel)";
drop(kTopicCamEvent, camEventJson(e));
}
// Commands: none arrive by themselves; inject() stands in for the broker,
// so --no-mqtt runs and tests can drive the remote-command path.
void inject(RemoteCommand rc) {
history_.record(/*outbound=*/false, Delivery::Ok, towerTopic(tower_, kTopicCommand),
rc.id.empty() ? rc.cmd : "{\"id\":" + jsonString(rc.id) + ",\"cmd\":" +
jsonString(rc.cmd) + "}");
pending_.push_back(std::move(rc));
}
std::vector<RemoteCommand> takeCommands() override {
std::vector<RemoteCommand> out;
out.swap(pending_);
return out;
}
void publishCommandReply(const CommandReply& r) override {
replies_.push_back(r);
drop(kTopicCommandReply, commandReplyJson(r));
}
const std::vector<CommandReply>& replies() const { return replies_; }
std::vector<ChannelMessage> recentMessages() const override { return history_.recent(); }
ChannelStats channelStats() const override { return history_.stats(); }
private:
void drop(const std::string& leaf, std::string payload) {
history_.record(/*outbound=*/true, Delivery::Dropped, towerTopic(tower_, leaf),
std::move(payload));
}
std::string tower_;
ChannelHistory history_;
std::vector<RemoteCommand> pending_;
std::vector<CommandReply> replies_;
};
} // namespace fgc