Index: tools/AgentSim/AgentSimController.cpp =================================================================== diff -u -rb1bab9e8d105f31bca82799af43ed354a4ab2df0 -r402926738e7394ee2d3dc7add2e6d755f06a289d --- tools/AgentSim/AgentSimController.cpp (.../AgentSimController.cpp) (revision b1bab9e8d105f31bca82799af43ed354a4ab2df0) +++ tools/AgentSim/AgentSimController.cpp (.../AgentSimController.cpp) (revision 402926738e7394ee2d3dc7add2e6d755f06a289d) @@ -11,7 +11,12 @@ * */ #include "AgentSimController.h" +#include "LeahiMsgProtoUtils.h" +#include +#include +#include + #include /*! @@ -91,8 +96,7 @@ result = _rxMsg.feed(_rxBuf); switch (result) { case AgentMessage::FeedResult::Complete: - logMessage(_rxMsg.msgId(), _rxMsg.sequence(), _rxMsg.payload()); - sendAck(_rxMsg.sequence()); + handleMessage(_rxMsg); _rxMsg.reset(); break; case AgentMessage::FeedResult::HeaderError: @@ -108,6 +112,61 @@ } /*! + * \brief AgentSimController::handleMessage + * \details Decodes a received frame and prints its typed body as JSON, generically + * via the protobuf descriptor pool (msgId -> message name -> dynamic parse). + * \param msg The complete AgentMessage frame. + */ +void AgentSimController::handleMessage(const AgentMessage &msg) +{ + const QByteArray payload = msg.payload(); + logMessage(msg.msgId(), msg.sequence(), payload); + + // Read the Header (field 1, shared by every typed message) to learn the msgId. + leahi::messages::Envelope envelope; + if (!envelope.ParseFromArray(payload.constData(), payload.size())) { + qWarning().noquote() << "AgentSim: could not parse Envelope header — frame dropped"; + return; + } + const leahi::messages::Header &header = envelope.header(); + + // Identify the concrete message type from the msgId and decode it generically. + const std::string &typeName = leahi::msgIdToProtoName(static_cast(header.msgid())); + if (typeName.empty()) { + qWarning().noquote() << QString("AgentSim: unknown msgId=0x%1 — cannot decode typed body") + .arg(header.msgid(), 4, 16, QChar('0')); + return; + } + + const google::protobuf::Descriptor *desc = + google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(typeName); + if (desc == nullptr) { + qWarning().noquote() << "AgentSim: no descriptor for" << QString::fromStdString(typeName); + return; + } + + google::protobuf::DynamicMessageFactory factory; + std::unique_ptr body(factory.GetPrototype(desc)->New()); + if (!body->ParseFromArray(payload.constData(), payload.size())) { + qWarning().noquote() << "AgentSim: could not parse" << QString::fromStdString(typeName); + return; + } + + std::string json; + google::protobuf::util::JsonPrintOptions opts; + opts.add_whitespace = true; + opts.always_print_primitive_fields = true; + google::protobuf::util::MessageToJsonString(*body, &json, opts); + + // protobuf renders msgId as a decimal integer; rewrite it as 0x + 4-digit hex. + QString jsonStr = QString::fromStdString(json); + jsonStr.replace(QString("\"msgId\": %1").arg(header.msgid()), + QString("\"msgId\": \"0x%1\"").arg(header.msgid(), 4, 16, QChar('0'))); + qDebug().noquote() << QString::fromStdString(typeName) << ":" << Qt::endl + << jsonStr; +} + +/*! * \brief AgentSimController::logMessage * \details Logs the message identifier, sequence number, and payload length. * \param msgId Message identifier from the parsed frame. @@ -121,19 +180,3 @@ .arg(sequence) .arg(payload.size()); } - -/*! - * \brief AgentSimController::sendAck - * \details Builds an Ack frame carrying \p sequence and writes it to the client socket. - * \param sequence Sequence number to echo back in the Ack frame. - */ -void AgentSimController::sendAck(quint16 sequence) -{ - if (!_client || _client->state() != QLocalSocket::ConnectedState) { - return; - } - const QByteArray frame = AgentMessage::build(AgentMessage::MsgId::Ack, sequence); - _client->write(frame); - _client->flush(); - qInfo().noquote() << QString("AgentSim: tx MsgId=Ack seq=%1").arg(sequence); -}