Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
… into main
  • Loading branch information
ClemensElflein committed Nov 4, 2024
2 parents 60e9fb7 + b21cf9a commit 59abe14
Show file tree
Hide file tree
Showing 16 changed files with 550 additions and 581 deletions.
12 changes: 6 additions & 6 deletions codegen/templates/ServiceInterfaceTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ cog.outl(f'#include <{service["interface_class_name"]}.hpp>')
#include <cstring>
#include <spdlog/spdlog.h>
/*[[[cog
cog.outl(f"void {service['interface_class_name']}::OnData(const std::string &uid, uint64_t timestamp, uint16_t target_id, const void *payload, size_t length) {{")
cog.outl(f"void {service['interface_class_name']}::OnData(uint16_t service_id, uint64_t timestamp, uint16_t target_id, const void *payload, size_t length) {{")
]]]*/
void ServiceTemplateInterfaceBase::OnData(const std::string &uid, uint64_t timestamp, uint16_t target_id, const void *payload, size_t length) {
void ServiceTemplateInterfaceBase::OnData(uint16_t service_id, uint64_t timestamp, uint16_t target_id, const void *payload, size_t length) {
//[[[end]]]
// Call the callback for this input
switch (target_id) {
Expand Down Expand Up @@ -103,13 +103,13 @@ bool ServiceTemplateInterfaceBase::SendExampleInput2(const uint32_t &data) {
//[[[end]]]

/*[[[cog
cog.outl(f"void {service['interface_class_name']}::OnServiceConnected(const std::string &uid) {{}};")
cog.outl(f"void {service['interface_class_name']}::OnServiceConnected(uint16_t service_id) {{}};")
cog.outl(f"void {service['interface_class_name']}::OnTransactionStart(uint64_t timestamp) {{}};")
cog.outl(f"void {service['interface_class_name']}::OnTransactionEnd() {{}};")
cog.outl(f"void {service['interface_class_name']}::OnServiceDisconnected(const std::string &uid) {{}};")
cog.outl(f"void {service['interface_class_name']}::OnServiceDisconnected(uint16_t service_id) {{}};")
]]]*/
void ServiceTemplateInterfaceBase::OnServiceConnected(const std::string &uid) {};
void ServiceTemplateInterfaceBase::OnServiceConnected(uint16_t service_id) {};
void ServiceTemplateInterfaceBase::OnTransactionStart(uint64_t timestamp) {};
void ServiceTemplateInterfaceBase::OnTransactionEnd() {};
void ServiceTemplateInterfaceBase::OnServiceDisconnected(const std::string &uid) {};
void ServiceTemplateInterfaceBase::OnServiceDisconnected(uint16_t service_id) {};
//[[[end]]]
6 changes: 3 additions & 3 deletions codegen/templates/ServiceInterfaceTemplate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ class ServiceTemplateInterfaceBase : public xbot::serviceif::ServiceInterfaceBas


private:
void OnData(const std::string &uid, uint64_t timestamp, uint16_t target_id, const void *payload, size_t buflen) final;
void OnServiceConnected(const std::string &uid) override;
void OnData(uint16_t service_id, uint64_t timestamp, uint16_t target_id, const void *payload, size_t buflen) final;
void OnServiceConnected(uint16_t service_id) override;
void OnTransactionStart(uint64_t timestamp) override;
void OnTransactionEnd() override;
void OnServiceDisconnected(const std::string &uid) override;
void OnServiceDisconnected(uint16_t service_id) override;
};


Expand Down
133 changes: 66 additions & 67 deletions include/xbot/datatypes/XbotHeader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,78 +8,77 @@
#include <cstdint>

namespace xbot::datatypes {
enum class MessageType : uint8_t {
// First bit 0, the payload is "raw".
// Use for simple, but frequent messages (e.g. sensor data, ack messages,
// ...).
UNKNOWN = 0x00,
// Use DATA for inputs and outputs.
DATA = 0x01,
// Use CONFIGURATION_REQUEST is sent by the service when it needs
// configuration
CONFIGURATION_REQUEST = 0x02,
// User CLAIM in order to claim a service. Payload is IP (uint32_t) and
// port(uint16_t). Service will reply with CLAM with arg1 == true for ack
CLAIM = 0x03,
// Heartbeat is sent regularly by service to show that its alive
HEARTBEAT = 0x04,
// Transaction bundles multiple data IOs separated with
// DataDescriptor headers.
TRANSACTION = 0x05,
// For remote debug logging
LOG = 0x7F,
// First bit 1, the payload is JSON encoded.
// Use for complex, infrequent, non-realtime critical messages (e.g. service
// discovery).
SERVICE_ADVERTISEMENT = 0x80,
SERVICE_QUERY = 0x81
};
enum class MessageType : uint8_t {
// First bit 0, the payload is "raw".
// Use for simple, but frequent messages (e.g. sensor data, ack messages,
// ...).
UNKNOWN = 0x00,
// Use DATA for inputs and outputs.
DATA = 0x01,
// Use CONFIGURATION_REQUEST is sent by the service when it needs
// configuration
CONFIGURATION_REQUEST = 0x02,
// User CLAIM in order to claim a service. Payload is IP (uint32_t) and
// port(uint16_t). Service will reply with CLAM with arg1 == true for ack
CLAIM = 0x03,
// Heartbeat is sent regularly by service to show that its alive
HEARTBEAT = 0x04,
// Transaction bundles multiple data IOs separated with
// DataDescriptor headers.
TRANSACTION = 0x05,
// For remote debug logging
LOG = 0x7F,
// First bit 1, the payload is JSON encoded.
// Use for complex, infrequent, non-realtime critical messages (e.g. service
// discovery).
SERVICE_ADVERTISEMENT = 0x80,
SERVICE_QUERY = 0x81
};

#pragma pack(push, 1)
struct XbotHeader {
// Version of the protocol, increment on breaking changes.
// 1 = initial release
uint8_t protocol_version{};
// 8 bit message type
MessageType message_type{};
// Flags.
// Bit 0: Reboot (1 after service started, 0 after sequence_no rolled over at
// least once)
uint8_t flags{};
uint8_t reserved1{};
uint16_t service_id{};
// Reserved for message specific payload (e.g. log level for log message)
// Log Message: Log level
// Transaction: Type: 0 = Data transaction, 1 = Configuration Transaction
uint8_t arg1{};
uint8_t reserved2{};
// Reserved for message specific payload (e.g. target_id for data message)
uint16_t arg2{};
// Sequence number, increment on each message. Clear "reboot" flag on roll
// over
uint16_t sequence_no{};
// Message timestamp. Unix timestamp in nanoseconds.
// Nanoseconds because we need 64 bit anyways and even with nanoseconds we
// have until year 2554 before it rolls over.
uint64_t timestamp{};
// Length of payload in bytes. Especially important for "raw" messages.
// Also this allows us to chain multiple xBot packets into a single UDP
// packet.
uint32_t payload_size{};
} __attribute__((packed));
struct XbotHeader {
// Version of the protocol, increment on breaking changes.
// 1 = initial release
uint8_t protocol_version{};
// 8 bit message type
MessageType message_type{};
// Flags.
// Bit 0: Reboot (1 after service started, 0 after sequence_no rolled over at
// least once)
uint8_t flags{};
uint8_t reserved1{};
uint16_t service_id{};
// Reserved for message specific payload (e.g. log level for log message)
// Log Message: Log level
// Transaction: Type: 0 = Data transaction, 1 = Configuration Transaction
uint8_t arg1{};
uint8_t reserved2{};
// Reserved for message specific payload (e.g. target_id for data message)
uint16_t arg2{};
// Sequence number, increment on each message. Clear "reboot" flag on roll
// over
uint16_t sequence_no{};
// Message timestamp. Unix timestamp in nanoseconds.
// Nanoseconds because we need 64 bit anyways and even with nanoseconds we
// have until year 2554 before it rolls over.
uint64_t timestamp{};
// Length of payload in bytes. Especially important for "raw" messages.
// Also this allows us to chain multiple xBot packets into a single UDP
// packet.
uint32_t payload_size{};
} __attribute__((packed));
#pragma pack(pop)

#pragma pack(push, 1)
struct DataDescriptor {
// Target ID for the next piece of data
uint16_t target_id{};
// Reserved for alignment and future use
uint16_t reserved{};
// Length of next payload in bytes.
uint32_t payload_size{};
} __attribute__((packed));
struct DataDescriptor {
// Target ID for the next piece of data
uint16_t target_id{};
// Reserved for alignment and future use
uint16_t reserved{};
// Length of next payload in bytes.
uint32_t payload_size{};
} __attribute__((packed));
#pragma pack(pop)

} // namespace xbot::datatypes
} // namespace xbot::datatypes

#endif // HEADER_HPP
1 change: 0 additions & 1 deletion libxbot-service-interface/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)

add_library(xbot-service-interface
src/Socket.cpp
src/ServiceInfo.cpp
include/xbot-service-interface/ServiceInterfaceBase.hpp
src/ServiceInterfaceBase.cpp
include/xbot-service-interface/XbotServiceInterface.hpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,33 @@
#include <xbot-service-interface/data/ServiceInfo.hpp>

namespace xbot::serviceif {

class ServiceDiscoveryCallbacks {
class ServiceDiscoveryCallbacks {
public:
virtual ~ServiceDiscoveryCallbacks() = default;

virtual bool OnServiceDiscovered(std::string uid) = 0;
virtual bool OnEndpointChanged(std::string uid, uint32_t old_ip,
virtual bool OnServiceDiscovered(uint16_t service_id) = 0;

virtual bool OnEndpointChanged(uint16_t service_id, uint32_t old_ip,
uint16_t old_port, uint32_t new_ip,
uint16_t new_port) = 0;
};
};

class ServiceDiscovery {
class ServiceDiscovery {
public:
virtual ~ServiceDiscovery() = default;

virtual void RegisterCallbacks(ServiceDiscoveryCallbacks *callbacks) = 0;

virtual void UnregisterCallbacks(ServiceDiscoveryCallbacks *callbacks) = 0;

/**
* Gets a copy of the ServiceInfo registered for this UID.
* Gets a copy of the ServiceInfo registered for this service_id.
* @return a unique_ptr to a copy of the ServiceInfo. nullptr if none was
* found.
*/
virtual std::unique_ptr<ServiceInfo> GetServiceInfo(
const std::string &uid) = 0;
};

} // namespace xbot::serviceif
uint16_t service_id) = 0;
};
} // namespace xbot::serviceif

#endif // SERVICEDISCOVERY_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@
#include <xbot/datatypes/XbotHeader.hpp>

namespace xbot::serviceif {

class ServiceIOCallbacks {
class ServiceIOCallbacks {
public:
virtual ~ServiceIOCallbacks() = default;

/**
* Called whenever a service is connected.
* Connected means that it was discovered and claimed successfully.
*/
virtual void OnServiceConnected(const std::string &uid) = 0;
virtual void OnServiceConnected(uint16_t service_id) = 0;

/**
* Called whenever a new transaction starts
Expand All @@ -33,46 +32,46 @@ class ServiceIOCallbacks {

/**
* Called whenever a packet is received from the specified service.
* @param uid service uid
* @param service_id service id
* @param timestamp timestamp
* @param target_id ID of the io target
* @param payload the raw payload
* @param buflen size of the payload buffer
*/
virtual void OnData(const std::string &uid, uint64_t timestamp,
virtual void OnData(uint16_t service_id, uint64_t timestamp,
uint16_t target_id, const void *payload,
size_t buflen) = 0;

/**
* Called whenever a service needs configuration. Whenever this is called,
* send a configuration transaction to the requesting service
* @param uid service uid
* @param service_id service id
*/
virtual bool OnConfigurationRequested(const std::string &uid) = 0;
virtual bool OnConfigurationRequested(uint16_t service_id) = 0;

/**
* Called whenever a service is disconnected.
* This could be due to timeout. After this OnData won't be called anymore
* with the uid. Note that OnServiceConnected might be called on reconnection.
* Then OnData will be called again as expected.
* @param uid the service's uid
* @param service_id the service's id
*/
virtual void OnServiceDisconnected(const std::string &uid) = 0;
};
virtual void OnServiceDisconnected(uint16_t service_id) = 0;
};

/**
* ServiceIO subscribes to ServiceDiscovery and claims all services anyone
* is interested in. It keeps track of the timeouts and redirects the actual
* data to the actual subscribers.
*/
class ServiceIO {
/**
* ServiceIO subscribes to ServiceDiscovery and claims all services anyone
* is interested in. It keeps track of the timeouts and redirects the actual
* data to the actual subscribers.
*/
class ServiceIO {
public:
/**
* Register callbacks for a specific uid
* @param uid the UID to listen to
* @param service_id the service ID to listen for
* @param callbacks pointer to the callbacks
*/
virtual void RegisterCallbacks(const std::string &uid,
virtual void RegisterCallbacks(uint16_t service_id,
ServiceIOCallbacks *callbacks) = 0;

/**
Expand All @@ -84,15 +83,15 @@ class ServiceIO {
/**
* Send data to a given service target
*/
virtual bool SendData(const std::string &uid,
virtual bool SendData(uint16_t service_id,
const std::vector<uint8_t> &data) = 0;

/**
* Call this to check if IO is still running.
* On shutdown this will return false, stop your interface then
*/
virtual bool OK() = 0;
};
} // namespace xbot::serviceif
};
} // namespace xbot::serviceif

#endif // SERVICEINTERFACEFACTORY_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
#include "XbotServiceInterface.hpp"

namespace xbot::serviceif {
class ServiceInterfaceBase : public xbot::serviceif::ServiceIOCallbacks,
public xbot::serviceif::ServiceDiscoveryCallbacks {
class ServiceInterfaceBase : public xbot::serviceif::ServiceIOCallbacks,
public xbot::serviceif::ServiceDiscoveryCallbacks {
public:
ServiceInterfaceBase(uint16_t service_id, std::string type, uint32_t version,
Context ctx);
Expand All @@ -29,9 +29,6 @@ class ServiceInterfaceBase : public xbot::serviceif::ServiceIOCallbacks,
// changes)
const uint32_t version_;

// uid of the bound service
std::string uid_{};

bool StartTransaction(bool is_configuration = false);

bool CommitTransaction();
Expand All @@ -40,8 +37,9 @@ class ServiceInterfaceBase : public xbot::serviceif::ServiceIOCallbacks,
bool is_configuration);

public:
bool OnServiceDiscovered(std::string uid) final;
bool OnEndpointChanged(std::string uid, uint32_t old_ip, uint16_t old_port,
bool OnServiceDiscovered(uint16_t service_id) final;

bool OnEndpointChanged(uint16_t service_id, uint32_t old_ip, uint16_t old_port,
uint32_t new_ip, uint16_t new_port) final;

private:
Expand All @@ -55,8 +53,10 @@ class ServiceInterfaceBase : public xbot::serviceif::ServiceIOCallbacks,

std::recursive_mutex state_mutex_{};

bool service_discovered_{false};

Context ctx{};
};
} // namespace xbot::serviceif
};
} // namespace xbot::serviceif

#endif // SERVICEINTERFACEBASE_HPP
Loading

0 comments on commit 59abe14

Please sign in to comment.