diff --git a/socket_input.cc b/socket_input.cc index f43cdfe..6a5e109 100644 --- a/socket_input.cc +++ b/socket_input.cc @@ -178,12 +178,40 @@ static inline int hexvalue(char c) { } } +boost::optional RawInput::ParseMetadataLine(const std::string &line) { + // Parse metadata line that starts with '!' + RawMessage::MetadataMap metadata; + + for (size_t i = 1; i < line.size();) { + auto equals = line.find('=', i); + auto semicolon = line.find(';', i); + if (equals == std::string::npos || semicolon == std::string::npos || semicolon < equals) { + // no more valid data + break; + } + + auto key = line.substr(i, equals - i); + auto value = line.substr(equals + 1, semicolon - equals - 1); + metadata[key] = value; + + i = semicolon + 1; + } + + return RawMessage(std::move(metadata)); +} + boost::optional RawInput::ParseLine(const std::string &line) { if (line.size() < 2) { // too short return boost::none; } + if (line[0] == '!') { + // metadata only + return ParseMetadataLine(line); + } + + // message with data payload if (line[0] != '-' && line[0] != '+') { // badly formatted return boost::none; diff --git a/socket_input.h b/socket_input.h index 1aa49f8..774c81b 100644 --- a/socket_input.h +++ b/socket_input.h @@ -36,6 +36,7 @@ namespace flightaware::uat { void ScheduleRead(); void ParseBuffer(); boost::optional ParseLine(const std::string &line); + boost::optional ParseMetadataLine(const std::string &line); void HandleError(const boost::system::error_code &ec); boost::asio::io_service &service_; diff --git a/uat_message.cc b/uat_message.cc index f33907b..214f962 100644 --- a/uat_message.cc +++ b/uat_message.cc @@ -28,16 +28,22 @@ std::ostream &flightaware::uat::operator<<(std::ostream &os, const RawMessage &m case MessageType::UPLINK: os << '+'; break; + case MessageType::METADATA: + os << '!'; + break; default: throw std::logic_error("unexpected message type"); } - os << std::setfill('0'); - for (auto b : message.Payload()) { - os << std::hex << std::setw(2) << (int)b; + if (message.Type() != MessageType::METADATA) { + os << std::setfill('0'); + for (auto b : message.Payload()) { + os << std::hex << std::setw(2) << (int)b; + } + + os << ";"; } - os << ";"; if (message.Errors() > 0) { os << "rs=" << std::dec << std::setw(0) << message.Errors() << ';'; } @@ -50,6 +56,10 @@ std::ostream &flightaware::uat::operator<<(std::ostream &os, const RawMessage &m if (message.RawTimestamp() != 0) { os << "rt=" << std::dec << std::setw(0) << message.RawTimestamp() << ';'; } + for (auto &i : message.Metadata()) { + os << i.first << '=' << i.second << ';'; + } + return os; } diff --git a/uat_message.h b/uat_message.h index b0a2939..8012ddc 100644 --- a/uat_message.h +++ b/uat_message.h @@ -20,7 +20,9 @@ namespace flightaware::uat { class RawMessage { public: - RawMessage() : type_(MessageType::INVALID), received_at_(0), errors_(0), rssi_(0) {} + using MetadataMap = std::map; + + RawMessage() : type_(MessageType::INVALID), received_at_(0), errors_(0), rssi_(0), raw_timestamp_(0) {} RawMessage(const Bytes &payload, std::uint64_t received_at, unsigned errors, float rssi, std::uint64_t raw_timestamp = 0) : payload_(payload), received_at_(received_at), errors_(errors), rssi_(rssi), raw_timestamp_(raw_timestamp) { switch (payload_.size()) { @@ -56,6 +58,10 @@ namespace flightaware::uat { } } + RawMessage(MetadataMap &&metadata) : type_(MessageType::METADATA), received_at_(0), errors_(0), rssi_(0.0), raw_timestamp_(0), metadata_(std::move(metadata)) {} + + RawMessage(const MetadataMap &metadata) : type_(MessageType::METADATA), received_at_(0), errors_(0), rssi_(0.0), raw_timestamp_(0), metadata_(metadata) {} + MessageType Type() const { return type_; } Bytes &Payload() { return payload_; } @@ -70,6 +76,8 @@ namespace flightaware::uat { std::uint64_t RawTimestamp() const { return raw_timestamp_; } + const MetadataMap &Metadata() const { return metadata_; } + // Number of raw bits in the message, excluding the sync bits unsigned BitLength() const { switch (type_) { @@ -149,6 +157,7 @@ namespace flightaware::uat { unsigned errors_; float rssi_; std::uint64_t raw_timestamp_; + MetadataMap metadata_; }; std::ostream &operator<<(std::ostream &os, const RawMessage &message); diff --git a/uat_protocol.h b/uat_protocol.h index 3a0d89d..8ec0940 100644 --- a/uat_protocol.h +++ b/uat_protocol.h @@ -10,7 +10,7 @@ #include namespace flightaware::uat { - enum class MessageType { DOWNLINK_SHORT, DOWNLINK_LONG, UPLINK, INVALID }; + enum class MessageType { DOWNLINK_SHORT, DOWNLINK_LONG, UPLINK, METADATA, INVALID }; const unsigned SYNC_BITS = 36; const std::uint64_t DOWNLINK_SYNC_WORD = 0xEACDDA4E2UL;