The mock server now correctly implements the newline-delimited JSON protocol observed in the Hyperion server and client code. - It properly parses incoming JSON streams line-by-line. - It creates QImage objects from the raw RGB data using the dimensions provided in the JSON payload. - It sends a success reply to the client after receiving an image. - This commit also updates lessons_learned.md with key findings from the debugging session.
96 lines
3.6 KiB
C++
96 lines
3.6 KiB
C++
#include <QCoreApplication>
|
|
#include <QTcpServer>
|
|
#include <QTcpSocket>
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QByteArray>
|
|
#include <QImage>
|
|
#include <QDebug>
|
|
|
|
class HyperionMock : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
HyperionMock(quint16 port, QObject *parent = nullptr) : QObject(parent)
|
|
{
|
|
_server = new QTcpServer(this);
|
|
connect(_server, &QTcpServer::newConnection, this, &HyperionMock::handleConnection);
|
|
if (!_server->listen(QHostAddress::Any, port)) {
|
|
qCritical() << "Failed to start mock server:" << _server->errorString();
|
|
} else {
|
|
qDebug() << "Mock server listening on port" << port;
|
|
}
|
|
}
|
|
|
|
private slots:
|
|
void handleConnection()
|
|
{
|
|
QTcpSocket *socket = _server->nextPendingConnection();
|
|
QByteArray *buffer = new QByteArray();
|
|
|
|
connect(socket, &QTcpSocket::readyRead, this, [this, socket, buffer]() {
|
|
buffer->append(socket->readAll());
|
|
|
|
int newlineIndex;
|
|
while ((newlineIndex = buffer->indexOf('\n')) != -1) {
|
|
// Extract the message including the newline
|
|
QByteArray jsonData = buffer->left(newlineIndex + 1);
|
|
buffer->remove(0, newlineIndex + 1);
|
|
|
|
QJsonDocument doc = QJsonDocument::fromJson(jsonData.trimmed());
|
|
if (doc.isObject()) {
|
|
QJsonObject obj = doc.object();
|
|
if (obj.contains("command") && obj["command"].toString() == "image") {
|
|
QJsonObject params = obj["params"].toObject();
|
|
int width = params["imagewidth"].toInt();
|
|
int height = params["imageheight"].toInt();
|
|
QByteArray imageData = QByteArray::fromBase64(params["imagedata"].toString().toUtf8());
|
|
|
|
if (width > 0 && height > 0 && !imageData.isEmpty()) {
|
|
QImage image(reinterpret_cast<const uchar*>(imageData.constData()), width, height, QImage::Format_RGB888);
|
|
if (!image.isNull()) {
|
|
QString filename = QString("received_frame_%1.png").arg(QUuid::createUuid().toString());
|
|
image.save(filename);
|
|
qDebug() << "Received and saved image:" << filename;
|
|
|
|
// Send success reply
|
|
QJsonObject reply;
|
|
reply["success"] = true;
|
|
reply["command"] = "image";
|
|
QByteArray replyData = QJsonDocument(reply).toJson(QJsonDocument::Compact);
|
|
replyData.append('\n');
|
|
socket->write(replyData);
|
|
|
|
} else {
|
|
qWarning() << "Failed to create QImage from raw data.";
|
|
}
|
|
} else {
|
|
qWarning() << "Invalid image dimensions or empty image data received.";
|
|
}
|
|
}
|
|
} else {
|
|
qWarning() << "Failed to parse JSON object:" << jsonData.trimmed();
|
|
}
|
|
}
|
|
});
|
|
|
|
connect(socket, &QTcpSocket::disconnected, this, [socket, buffer]() {
|
|
socket->deleteLater();
|
|
delete buffer;
|
|
});
|
|
}
|
|
|
|
|
|
private:
|
|
QTcpServer *_server;
|
|
};
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
QCoreApplication app(argc, argv);
|
|
HyperionMock mock(19444);
|
|
return app.exec();
|
|
}
|
|
|
|
#include "hyperion-mock.moc"
|