From 7470d58b135e48c1825d193783c125aa22e5bb77 Mon Sep 17 00:00:00 2001 From: Hoop77 <p.badenhoop@gmx.de> Date: Sat, 20 Jan 2018 11:30:48 +0100 Subject: [PATCH] platoon should be standard confirm now --- NetworkingLib/include/Frame.h | 5 +- NetworkingLib/include/Utils.h | 21 ++++++-- NetworkingLib/src/Socket.cpp | 2 +- NetworkingLib/src/Stream.cpp | 2 +- Protocol/README.md | 6 +++ Protocol/include/PlatoonMessage.h | 80 ++++++++++++++++++------------- 6 files changed, 72 insertions(+), 44 deletions(-) diff --git a/NetworkingLib/include/Frame.h b/NetworkingLib/include/Frame.h index 26c840b1..380ed364 100644 --- a/NetworkingLib/include/Frame.h +++ b/NetworkingLib/include/Frame.h @@ -22,10 +22,7 @@ public: Frame(const std::uint8_t * data, std::uint32_t numDataBytes) : data(data), numDataBytes(numDataBytes) { - header[0] = utils::byte<0>(numDataBytes); - header[1] = utils::byte<1>(numDataBytes); - header[2] = utils::byte<2>(numDataBytes); - header[3] = utils::byte<3>(numDataBytes); + utils::toBigEndian<4>(header, numDataBytes); } Frame(const Frame &) = delete; diff --git a/NetworkingLib/include/Utils.h b/NetworkingLib/include/Utils.h index b4bb54cd..5635b287 100644 --- a/NetworkingLib/include/Utils.h +++ b/NetworkingLib/include/Utils.h @@ -12,16 +12,27 @@ namespace networking namespace utils { -template<std::size_t index, typename Int> -inline std::uint8_t byte(Int var) -{ return (std::uint8_t) ((var >> 8*index) & 0x000000ff); } +template<std::size_t numBytes, typename Int> +inline void toBigEndian(std::uint8_t * dest, Int src) +{ + std::size_t bitsToShift = numBytes * 8; + for (std::size_t i = 0; i < numBytes; i++) + { + bitsToShift -= 8; + dest[i] = (std::uint8_t) ((src >> bitsToShift) & 0x000000ff); + } +}; template<std::size_t numBytes, typename Int> -inline Int bytesToInt(const std::uint8_t * bytes) +inline Int fromBigEndian(const std::uint8_t * bytes) { Int result = 0; + std::size_t bitsToShift = numBytes * 8; for (std::size_t i = 0; i < numBytes; i++) - result += ((Int) bytes[i]) << (i*8); + { + bitsToShift -= 8; + result += ((Int) bytes[i]) << bitsToShift; + } return result; } diff --git a/NetworkingLib/src/Socket.cpp b/NetworkingLib/src/Socket.cpp index 20a21e96..d21db207 100644 --- a/NetworkingLib/src/Socket.cpp +++ b/NetworkingLib/src/Socket.cpp @@ -16,7 +16,7 @@ bool stringFromBuffer(std::string & data, std::vector<char> & buffer, std::size_ if (bytesTransferred < 4) return false; - auto numDataBytes = utils::bytesToInt<4, std::uint32_t>((const std::uint8_t *) buffer.data()); + auto numDataBytes = utils::fromBigEndian<4, std::uint32_t>((const std::uint8_t *) buffer.data()); if (bytesTransferred < 4 + numDataBytes) return false; diff --git a/NetworkingLib/src/Stream.cpp b/NetworkingLib/src/Stream.cpp index f4be80af..3884231f 100644 --- a/NetworkingLib/src/Stream.cpp +++ b/NetworkingLib/src/Stream.cpp @@ -23,7 +23,7 @@ std::string stringFromStreambuf(boost::asio::streambuf & streambuf, std::size_t std::uint32_t numDataBytesFromBuffer(boost::asio::streambuf & streambuf) { auto numDataBytesStr = stringFromStreambuf(streambuf, 4); - return utils::bytesToInt<4, std::uint32_t>((const std::uint8_t *) numDataBytesStr.c_str()); + return utils::fromBigEndian<4, std::uint32_t>((const std::uint8_t *) numDataBytesStr.c_str()); } std::size_t getNumRemainingBytes(std::size_t numBytesTransferred, std::uint32_t numDataBytes) diff --git a/Protocol/README.md b/Protocol/README.md index 22d71294..69ada00b 100644 --- a/Protocol/README.md +++ b/Protocol/README.md @@ -16,6 +16,9 @@ Here we suppose to run a platoon as leader: networking::Networking net; // Create a leader. auto leader = protocol::LeaderVehicle::create(net, 1); // 1 = vehicleId +// Add endpoints which we may request a platoon to create with. +leader->addVehicleEndpoint(2, "192.168.100.30); +leader->addVehicleEndpoint(3, "192.168.134.5); // Set the initial platoon configuration. // This can be set at anytime and will be send to the following vehicles. leader->setPlatoonConfig(protocol::PlatoonConfig{10.0f, 20.0f}); @@ -35,6 +38,9 @@ And on another machine, we're running a follower: networking::Networking net; // Create a leader. auto follower = protocol::FollowerVehicle::create(net, 2); // 2 = vehicleId +// Add endpoints which we may request a platoon to create with. +follower->addVehicleEndpoint(2, "192.168.100.30); +follower->addVehicleEndpoint(3, "192.168.134.5); // Register a callback to receive platoon configuration updates (ps and ipd). follower->setOnUpdatePlatoonConfigCallback( [](const protocol::PlatoonConfig & config){/* Received updated platoonConfig. */}); diff --git a/Protocol/include/PlatoonMessage.h b/Protocol/include/PlatoonMessage.h index eb4777ae..86c1268e 100644 --- a/Protocol/include/PlatoonMessage.h +++ b/Protocol/include/PlatoonMessage.h @@ -10,12 +10,14 @@ #include "Protocol.h" #include "json.hpp" #include <NetworkingLib/Message.h> +#include <unordered_set> namespace protocol { namespace messageTypes { + constexpr MessageType LV_BROADCAST = 0x00000001; constexpr MessageType FV_HEARTBEAT = 0x00000002; constexpr MessageType LV_REQUEST = 0x00000004; @@ -23,11 +25,20 @@ constexpr MessageType FV_REQUEST = 0x00000008; constexpr MessageType ACCEPT_RESPONSE = 0x00000010; constexpr MessageType REJECT_RESPONSE = 0x00000020; constexpr MessageType LEAVE_PLATOON = 0x00000040; + +const std::unordered_set<MessageType> standardMessageTypes{ + LV_BROADCAST, FV_HEARTBEAT, LV_REQUEST, FV_REQUEST, ACCEPT_RESPONSE, REJECT_RESPONSE, LEAVE_PLATOON}; + +inline bool isStandardMessageType(MessageType messageType) +{ + return messageTypes::standardMessageTypes.find(messageType) != messageTypes::standardMessageTypes.end(); +} + } struct PlatoonMessage { - static constexpr std::size_t MAX_SIZE = 512; + static constexpr std::size_t MAX_SIZE = 256; PlatoonMessage() {} @@ -75,31 +86,6 @@ struct PlatoonMessage PlatoonSpeed platoonSpeed; InnerPlatoonDistance innerPlatoonDistance; }; -} - -namespace nlohmann -{ - -template<> -struct adl_serializer<protocol::PlatoonMessage> -{ - static void to_json(json & j, const protocol::PlatoonMessage & message) - { - j = json{{"vehicleId", message.vehicleId}, - {"platoonId", message.platoonId}, - {"platoonSpeed", message.platoonSpeed}, - {"innerPlatoonDistance", message.innerPlatoonDistance}}; - } - - static void from_json(const json & j, protocol::PlatoonMessage & message) - { - using namespace protocol; - message.vehicleId = j.at("vehicleId").get<VehicleId>(); - message.platoonId = j.at("platoonId").get<PlatoonId>(); - message.platoonSpeed = j.at("platoonSpeed").get<PlatoonSpeed>(); - message.innerPlatoonDistance = j.at("innerPlatoonDistance").get<InnerPlatoonDistance>(); - } -}; } @@ -116,15 +102,29 @@ struct Encoder<protocol::PlatoonMessage> using namespace protocol; auto messageType = message.messageType; + + if (!messageTypes::isStandardMessageType(messageType)) + throw 0; // Throw something to signal a failed encoding. + // 4 bytes for message type data = std::string(4, '\0'); - data[0] = networking::utils::byte<0>(messageType); - data[1] = networking::utils::byte<1>(messageType); - data[2] = networking::utils::byte<2>(messageType); - data[3] = networking::utils::byte<3>(messageType); + + std::uint8_t numDataBytes[sizeof(MessageType)]; + networking::utils::toBigEndian<4>(numDataBytes, messageType); + + for (std::size_t i = 0; i < sizeof(MessageType); i++) + data[i] = numDataBytes[i]; using json = nlohmann::json; - json j = message; + auto j = json{{"vehicleId", message.vehicleId}, + {"platoonId", message.platoonId}}; + + if (messageType == messageTypes::LV_BROADCAST) + { + j["ps"] = message.platoonSpeed; + j["ipd"] = message.innerPlatoonDistance; + } + data.append(j.dump()); } }; @@ -141,9 +141,23 @@ struct Decoder<protocol::PlatoonMessage> using json = nlohmann::json; auto j = json::parse(data.begin() + sizeof(MessageType), data.end()); - message = j; - message.messageType = networking::utils::bytesToInt<sizeof(MessageType), MessageType>( + + auto messageType = networking::utils::fromBigEndian<sizeof(MessageType), MessageType>( (const std::uint8_t *) data.c_str()); + + // We only know message types conforming to the standard protocol specification. + if (!messageTypes::isStandardMessageType(messageType)) + throw 0; + + message.messageType = messageType; + message.vehicleId = j.at("vehicleId").get<VehicleId>(); + message.platoonId = j.at("platoonId").get<PlatoonId>(); + + if (messageType == messageTypes::LV_BROADCAST) + { + message.platoonSpeed = j.at("ps").get<PlatoonSpeed>(); + message.innerPlatoonDistance = j.at("ipd").get<InnerPlatoonDistance>(); + } }; }; -- GitLab