fwt_software/include/fgc/IControlChannel.h

87 lines
3.3 KiB
C++

#pragma once
#include <string>
#include <vector>
namespace fgc {
// Remote control input (was struct mqtt_sub_data). The *_available flags mark
// whether a fresh value arrived since the last poll().
struct ControlCommand {
bool control_code_available = false;
int control_code = 0; // 0 = automatic sweep, 1 = directed to target heading
bool heading_available = false;
std::string target_heading; // kept as string; the yaw target in degrees
};
// Notification published after an image is captured and saved.
struct CamEvent {
std::string tower; // tower / FWT name
std::string camera; // "RGB" / "ACR" / "NIR"
int heading_decideg = 0; // yaw heading * 10 (one decimal as integer)
int pitch_decideg = 0; // pitch elevation * 10 (one decimal as integer)
long long timestamp_ms = 0; // Unix epoch ms; matches the image filename
};
// Ambient temperature/humidity reading published once per fresh sensor sample.
struct EnvEvent {
std::string tower;
float temp_c = 0.0f;
float humidity_pct = 0.0f;
long long timestamp_ms = 0;
};
// What became of an outbound message. Dropped and Failed are separated because
// they mean different things operationally: Dropped is "the link was down and we
// discarded it silently", Failed is "the broker or library rejected it".
// Inbound messages are always Ok.
enum class Delivery { Ok, Dropped, Failed };
// One message that crossed the control channel, for the connectivity view.
struct ChannelMessage {
long long timestamp_ms = 0;
bool outbound = true; // PUB (ours) vs RX (broker's)
Delivery delivery = Delivery::Ok;
std::string topic;
std::string payload;
};
// Cumulative channel counters since start-up.
struct ChannelStats {
long long published_ok = 0;
long long published_dropped = 0; // attempted while disconnected: silently discarded
long long published_failed = 0; // the broker/library rejected it
long long received = 0;
long long connects = 0; // successful (re)connections
long long last_connect_ms = 0, last_loss_ms = 0;
std::string last_status_payload; // what actually went out on StatusCode
};
// Abstraction over the remote control/telemetry channel. Implemented by
// MqttControlChannel (Eclipse Paho) and NullControlChannel (no broker; used
// for development - publishes are dropped and poll() yields a default).
class IControlChannel {
public:
virtual ~IControlChannel() = default;
// Returns true once usable. NullControlChannel always succeeds.
virtual bool connect() = 0;
virtual void disconnect() = 0;
virtual bool connected() const = 0;
virtual void publishStatus(int code) = 0;
virtual void publishCamEvent(const CamEvent& event) = 0;
virtual void publishEnv(const EnvEvent& event) = 0;
// Latest control input; clears the *_available flags so each update is
// acted on once.
virtual ControlCommand poll() = 0;
// Recent traffic and counters for the connectivity ('m') view. Default: none,
// so an implementation that keeps no history needs no changes.
virtual std::vector<ChannelMessage> recentMessages() const { return {}; }
virtual ChannelStats channelStats() const { return {}; }
};
} // namespace fgc