102 lines
4.3 KiB
C++
102 lines
4.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
|
|
};
|
|
|
|
// A console command that arrived over MQTT, on GGS/FWT/<tower>/Command. It is
|
|
// run by the same handleCommand() as a typed one, on the control thread.
|
|
struct RemoteCommand {
|
|
std::string id; // chosen by the sender, echoed in the reply; may be empty
|
|
std::string cmd; // the command line, exactly as typed at the console
|
|
long long received_ms = 0;
|
|
bool retained = false; // a retained message: never run (it would re-run on reconnect)
|
|
std::string error; // non-empty: the payload could not be read; reply, do not run
|
|
};
|
|
|
|
// The tower's answer, on GGS/FWT/<tower>/CommandReply.
|
|
struct CommandReply {
|
|
std::string id;
|
|
std::string cmd;
|
|
std::string level = "info"; // most severe line: info / warn / error
|
|
std::vector<std::string> lines; // what the command logged while it ran
|
|
bool truncated = false;
|
|
};
|
|
|
|
// 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;
|
|
|
|
// Latest control input; clears the *_available flags so each update is
|
|
// acted on once.
|
|
virtual ControlCommand poll() = 0;
|
|
|
|
// Commands received since the last call, oldest first; clears them. And the
|
|
// answer to one. Defaults: none / dropped, for a channel that takes no commands.
|
|
virtual std::vector<RemoteCommand> takeCommands() { return {}; }
|
|
virtual void publishCommandReply(const CommandReply& /*reply*/) {}
|
|
|
|
// 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
|