diff --git a/src/hyperion-v4l2/CMakeLists.txt b/src/hyperion-v4l2/CMakeLists.txt index 603ce42e..58b62ac1 100644 --- a/src/hyperion-v4l2/CMakeLists.txt +++ b/src/hyperion-v4l2/CMakeLists.txt @@ -42,7 +42,6 @@ add_executable(hyperion-v4l2 target_link_libraries(hyperion-v4l2 getoptPlusPlus - jsoncpp hyperion-utils ${PROTOBUF_LIBRARIES} pthread diff --git a/src/hyperion-v4l2/ProtoConnection.cpp b/src/hyperion-v4l2/ProtoConnection.cpp index f679bcbc..07544a8e 100644 --- a/src/hyperion-v4l2/ProtoConnection.cpp +++ b/src/hyperion-v4l2/ProtoConnection.cpp @@ -38,26 +38,17 @@ ProtoConnection::~ProtoConnection() _socket.close(); } -void ProtoConnection::setColor(std::vector colors, int priority, int duration) +void ProtoConnection::setColor(const ColorRgb & color, int priority, int duration) { - // create command - Json::Value command; - command["command"] = "color"; - command["priority"] = priority; - Json::Value & rgbValue = command["color"]; - for (const QColor & color : colors) - { - rgbValue.append(color.red()); - rgbValue.append(color.green()); - rgbValue.append(color.blue()); - } - if (duration > 0) - { - command["duration"] = duration; - } + proto::HyperionRequest request; + request.set_command(proto::HyperionRequest::COLOR); + proto::ColorRequest * colorRequest = request.MutableExtension(proto::ColorRequest::colorRequest); + colorRequest->set_rgbcolor((color.red << 16) | (color.green << 8) | color.blue); + colorRequest->set_priority(priority); + colorRequest->set_duration(duration); // send command message - Json::Value reply = sendMessage(command); + proto::HyperionReply reply = sendMessage(request); // parse reply message parseReply(reply); @@ -65,40 +56,31 @@ void ProtoConnection::setColor(std::vector colors, int priority, int dur void ProtoConnection::setImage(const Image &image, int priority, int duration) { - // ensure the image has RGB888 format - QByteArray binaryImage = QByteArray::fromRawData(reinterpret_cast(image.memptr()), image.width() * image.height() * 3); - const QByteArray base64Image = binaryImage.toBase64(); - - // create command - Json::Value command; - command["command"] = "image"; - command["priority"] = priority; - command["imagewidth"] = image.width(); - command["imageheight"] = image.height(); - command["imagedata"] = std::string(base64Image.data(), base64Image.size()); - if (duration > 0) - { - command["duration"] = duration; - } + proto::HyperionRequest request; + request.set_command(proto::HyperionRequest::IMAGE); + proto::ImageRequest * imageRequest = request.MutableExtension(proto::ImageRequest::imageRequest); + imageRequest->set_imagedata(image.memptr(), image.width() * image.height() * 3); + imageRequest->set_imagewidth(image.width()); + imageRequest->set_imageheight(image.height()); + imageRequest->set_priority(priority); + imageRequest->set_duration(duration); // send command message - Json::Value reply = sendMessage(command); + proto::HyperionReply reply = sendMessage(request); // parse reply message - parseReply(reply); +// parseReply(reply); } void ProtoConnection::clear(int priority) { - std::cout << "Clear priority channel " << priority << std::endl; - - // create command - Json::Value command; - command["command"] = "clear"; - command["priority"] = priority; + proto::HyperionRequest request; + request.set_command(proto::HyperionRequest::CLEAR); + proto::ClearRequest * clearRequest = request.MutableExtension(proto::ClearRequest::clearRequest); + clearRequest->set_priority(priority); // send command message - Json::Value reply = sendMessage(command); + proto::HyperionReply reply = sendMessage(request); // parse reply message parseReply(reply); @@ -106,35 +88,44 @@ void ProtoConnection::clear(int priority) void ProtoConnection::clearAll() { - std::cout << "Clear all priority channels" << std::endl; - - // create command - Json::Value command; - command["command"] = "clearall"; + proto::HyperionRequest request; + request.set_command(proto::HyperionRequest::CLEARALL); // send command message - Json::Value reply = sendMessage(command); + proto::HyperionReply reply = sendMessage(request); // parse reply message parseReply(reply); } -Json::Value ProtoConnection::sendMessage(const Json::Value & message) +proto::HyperionReply ProtoConnection::sendMessage(const proto::HyperionRequest &message) { // serialize message (FastWriter already appends a newline) - std::string serializedMessage = Json::FastWriter().write(message); + std::string serializedMessage = message.SerializeAsString(); + + int length = serializedMessage.size(); + const uint8_t header[] = { + uint8_t((length >> 24) & 0xFF), + uint8_t((length >> 16) & 0xFF), + uint8_t((length >> 8) & 0xFF), + uint8_t((length ) & 0xFF)}; // write message - _socket.write(serializedMessage.c_str()); + int count = 0; + count += _socket.write(reinterpret_cast(header), 4); + count += _socket.write(reinterpret_cast(serializedMessage.data()), length); if (!_socket.waitForBytesWritten()) { throw std::runtime_error("Error while writing data to host"); } + /* // read reply data QByteArray serializedReply; - while (!serializedReply.contains('\n')) + length = -1; + while (serializedReply.size() != length) { + std::cout << length << std::endl; // receive reply if (!_socket.waitForReadyRead()) { @@ -142,39 +133,40 @@ Json::Value ProtoConnection::sendMessage(const Json::Value & message) } serializedReply += _socket.readAll(); - } - int bytes = serializedReply.indexOf('\n') + 1; // Find the end of message + if (length < 0 && serializedReply.size() >= 4) + { + std::cout << (int) serializedReply[3] << std::endl; + std::cout << (int) serializedReply[2] << std::endl; + std::cout << (int) serializedReply[1] << std::endl; + std::cout << (int) serializedReply[0] << std::endl; + + length = (uint8_t(serializedReply[0]) << 24) | (uint8_t(serializedReply[1]) << 16) | (uint8_t(serializedReply[2]) << 8) | uint8_t(serializedReply[3]) ; + } + } + + std::cout << length << std::endl; +*/ // parse reply data - Json::Reader jsonReader; - Json::Value reply; - if (!jsonReader.parse(serializedReply.constData(), serializedReply.constData() + bytes, reply)) - { - throw std::runtime_error("Error while parsing reply: invalid json"); - } - + proto::HyperionReply reply; +// reply.ParseFromArray(serializedReply.constData()+4, length); return reply; } -bool ProtoConnection::parseReply(const Json::Value &reply) +bool ProtoConnection::parseReply(const proto::HyperionReply &reply) { bool success = false; - std::string reason = "No error info"; - try + if (!reply.success()) { - success = reply.get("success", false).asBool(); - if (!success) - reason = reply.get("error", reason).asString(); - } - catch (const std::runtime_error &) - { - // Some json parsing error: ignore and set parsing error - } - - if (!success) - { - throw std::runtime_error("Error: " + reason); + if (reply.has_error()) + { + throw std::runtime_error("Error: " + reply.error()); + } + else + { + throw std::runtime_error("Error: No error info"); + } } return success; diff --git a/src/hyperion-v4l2/ProtoConnection.h b/src/hyperion-v4l2/ProtoConnection.h index cbff597d..b20faf34 100644 --- a/src/hyperion-v4l2/ProtoConnection.h +++ b/src/hyperion-v4l2/ProtoConnection.h @@ -14,7 +14,7 @@ #include // jsoncpp includes -#include +#include /// /// Connection class to setup an connection to the hyperion server and execute commands @@ -41,7 +41,7 @@ public: /// @param priority The priority /// @param duration The duration in milliseconds /// - void setColor(std::vector color, int priority, int duration); + void setColor(const ColorRgb & color, int priority, int duration = 1); /// /// Set the leds according to the given image (assume the image is stretched to the display size) @@ -50,7 +50,7 @@ public: /// @param priority The priority /// @param duration The duration in milliseconds /// - void setImage(const Image & image, int priority, int duration); + void setImage(const Image & image, int priority, int duration = -1); /// /// Clear the given priority channel @@ -66,13 +66,13 @@ public: private: /// - /// Send a json command message and receive its reply + /// Send a command message and receive its reply /// /// @param message The message to send /// /// @return The returned reply /// - Json::Value sendMessage(const Json::Value & message); + proto::HyperionReply sendMessage(const proto::HyperionRequest & message); /// /// Parse a reply message @@ -81,7 +81,7 @@ private: /// /// @return true if the reply indicates success /// - bool parseReply(const Json::Value & reply); + bool parseReply(const proto::HyperionReply & reply); private: /// The TCP-Socket with the connection to the server