diff --git a/src/viam/sdk/common/client_helper.hpp b/src/viam/sdk/common/client_helper.hpp index 95d1f8f09..c68e7fe85 100644 --- a/src/viam/sdk/common/client_helper.hpp +++ b/src/viam/sdk/common/client_helper.hpp @@ -8,11 +8,19 @@ #include #include +namespace grpc { + +class Status; + +} // namespace grpc + namespace viam { namespace sdk { namespace client_helper_details { + [[noreturn]] void errorHandlerReturnedUnexpectedly(const ::grpc::Status&) noexcept; + } // namespace client_helper_details // Method type for a gRPC call that returns a response message type. @@ -59,7 +67,8 @@ class ClientHelper { ProtoValue value = key->second; debug_key_ = *value.get(); } - *request_.mutable_extra() = v2::to_proto(extra); + + proto_convert_details::to_proto{}(extra, request_.mutable_extra()); return with(std::forward(rsc)); } @@ -102,7 +111,7 @@ class ClientHelper { while (reader->Read(&response_)) { if (!rhc(response_)) { cancelled_by_handler = true; - static_cast<::grpc::ClientContext*>(ctx)->TryCancel(); + ctx.try_cancel(); break; } } diff --git a/src/viam/sdk/common/service_helper.hpp b/src/viam/sdk/common/service_helper.hpp index 0dd193fcb..b9435bbb3 100644 --- a/src/viam/sdk/common/service_helper.hpp +++ b/src/viam/sdk/common/service_helper.hpp @@ -2,6 +2,8 @@ #include +#include + #include namespace viam { diff --git a/src/viam/sdk/common/utils.cpp b/src/viam/sdk/common/utils.cpp index 098188ba9..fdd03b6da 100644 --- a/src/viam/sdk/common/utils.cpp +++ b/src/viam/sdk/common/utils.cpp @@ -4,13 +4,16 @@ #include #include +#include +#include +#include + #include #include #include #include #include #include -#include #include @@ -22,52 +25,44 @@ namespace viam { namespace sdk { -std::vector string_to_bytes(const std::string& s) { - std::vector bytes(s.begin(), s.end()); - return bytes; -}; - -std::string bytes_to_string(const std::vector& b) { - std::string img_string(b.begin(), b.end()); - return img_string; -}; - -time_pt timestamp_to_time_pt(const google::protobuf::Timestamp& timestamp) { - return time_pt{std::chrono::seconds{timestamp.seconds()} + - std::chrono::nanoseconds{timestamp.nanos()}}; +bool operator==(const response_metadata& lhs, const response_metadata& rhs) { + return lhs.captured_at == rhs.captured_at; } -google::protobuf::Timestamp time_pt_to_timestamp(time_pt tp) { +namespace proto_convert_details { + +void to_proto::operator()(time_pt tp, google::protobuf::Timestamp* result) const { const std::chrono::nanoseconds since_epoch = tp.time_since_epoch(); const auto sec_floor = std::chrono::duration_cast(since_epoch); const std::chrono::nanoseconds nano_part = since_epoch - sec_floor; - google::protobuf::Timestamp result; - - result.set_seconds(sec_floor.count()); - result.set_nanos(static_cast(nano_part.count())); - - return result; + result->set_seconds(sec_floor.count()); + result->set_nanos(static_cast(nano_part.count())); } -response_metadata response_metadata::from_proto(const viam::common::v1::ResponseMetadata& proto) { - response_metadata metadata; - metadata.captured_at = timestamp_to_time_pt(proto.captured_at()); - return metadata; +time_pt from_proto::operator()( + const google::protobuf::Timestamp* timestamp) const { + return time_pt{std::chrono::seconds{timestamp->seconds()} + + std::chrono::nanoseconds{timestamp->nanos()}}; } -viam::common::v1::ResponseMetadata response_metadata::to_proto(const response_metadata& metadata) { - viam::common::v1::ResponseMetadata proto; - google::protobuf::Timestamp ts = time_pt_to_timestamp(metadata.captured_at); - *proto.mutable_captured_at() = std::move(ts); - return proto; +void to_proto::operator()(std::chrono::microseconds duration, + google::protobuf::Duration* proto) const { + namespace sc = std::chrono; + + const sc::seconds seconds = sc::duration_cast(duration); + const sc::nanoseconds nanos = duration - seconds; + + proto->set_nanos(static_cast(nanos.count())); + proto->set_seconds(seconds.count()); } -std::chrono::microseconds from_proto(const google::protobuf::Duration& proto) { +std::chrono::microseconds from_proto::operator()( + const google::protobuf::Duration* proto) const { namespace sc = std::chrono; - const sc::seconds seconds_part{proto.seconds()}; - const sc::nanoseconds nanos_part{proto.nanos()}; + const sc::seconds seconds_part{proto->seconds()}; + const sc::nanoseconds nanos_part{proto->nanos()}; const sc::microseconds from_seconds = sc::duration_cast(seconds_part); sc::microseconds from_nanos = sc::duration_cast(nanos_part); @@ -80,16 +75,26 @@ std::chrono::microseconds from_proto(const google::protobuf::Duration& proto) { return from_seconds + from_nanos; } -google::protobuf::Duration to_proto(std::chrono::microseconds duration) { - namespace sc = std::chrono; +void to_proto::operator()(const response_metadata& self, + common::v1::ResponseMetadata* proto) const { + *(proto->mutable_captured_at()) = v2::to_proto(self.captured_at); +} - const sc::seconds seconds = sc::duration_cast(duration); - const sc::nanoseconds nanos = duration - seconds; +response_metadata from_proto::operator()( + const common::v1::ResponseMetadata* proto) const { + return {v2::from_proto(proto->captured_at())}; +} + +} // namespace proto_convert_details + +std::vector string_to_bytes(const std::string& s) { + std::vector bytes(s.begin(), s.end()); + return bytes; +} - google::protobuf::Duration proto; - proto.set_nanos(static_cast(nanos.count())); - proto.set_seconds(seconds.count()); - return proto; +std::string bytes_to_string(const std::vector& b) { + std::string img_string(b.begin(), b.end()); + return img_string; } void set_logger_severity_from_args(int argc, char** argv) { @@ -101,14 +106,6 @@ void set_logger_severity_from_args(int argc, char** argv) { boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::info); } -bool operator==(const response_metadata& lhs, const response_metadata& rhs) { - return lhs.captured_at == rhs.captured_at; -} - -void ClientContext::set_client_ctx_authority_() { - wrapped_context_.set_authority("viam-placeholder"); -} - std::string random_debug_key() { static const char alphanum[] = "abcdefghijklmnopqrstuvwxyz"; static std::default_random_engine generator( @@ -154,25 +151,35 @@ ProtoStruct with_debug_entry(ProtoStruct&& map) { return map; } -void ClientContext::set_debug_key(const std::string& debug_key) { - wrapped_context_.AddMetadata("dtname", debug_key); -} - -void ClientContext::add_viam_client_version_() { - wrapped_context_.AddMetadata("viam_client", impl::k_version); -} - -ClientContext::ClientContext() { +ClientContext::ClientContext() : wrapped_context_(std::make_unique()) { set_client_ctx_authority_(); add_viam_client_version_(); } +ClientContext::~ClientContext() = default; + ClientContext::operator const grpc::ClientContext*() const { - return &wrapped_context_; + return wrapped_context_.get(); } ClientContext::operator grpc::ClientContext*() { - return &wrapped_context_; + return wrapped_context_.get(); +} + +void ClientContext::try_cancel() { + wrapped_context_->TryCancel(); +} + +void ClientContext::set_debug_key(const std::string& debug_key) { + wrapped_context_->AddMetadata("dtname", debug_key); +} + +void ClientContext::set_client_ctx_authority_() { + wrapped_context_->set_authority("viam-placeholder"); +} + +void ClientContext::add_viam_client_version_() { + wrapped_context_->AddMetadata("viam_client", impl::k_version); } bool from_dm_from_extra(const ProtoStruct& extra) { diff --git a/src/viam/sdk/common/utils.hpp b/src/viam/sdk/common/utils.hpp index 41fc6b91a..cb3c76532 100644 --- a/src/viam/sdk/common/utils.hpp +++ b/src/viam/sdk/common/utils.hpp @@ -1,14 +1,33 @@ #pragma once +#include + #include #include -#include - #include #include #include +namespace google { +namespace protobuf { + +class Duration; +class Timestamp; + +} // namespace protobuf +} // namespace google + +namespace viam { +namespace common { +namespace v1 { + +class ResponseMetadata; + +} +} // namespace common +} // namespace viam + namespace viam { namespace sdk { @@ -22,25 +41,47 @@ using time_pt = std::chrono::time_point +struct to_proto { + void operator()(time_pt, google::protobuf::Timestamp*) const; +}; + +template <> +struct from_proto { + time_pt operator()(const google::protobuf::Timestamp*) const; +}; + +template <> +struct to_proto { + void operator()(std::chrono::microseconds, google::protobuf::Duration*) const; +}; + +template <> +struct from_proto { + std::chrono::microseconds operator()(const google::protobuf::Duration*) const; +}; + +template <> +struct to_proto { + void operator()(const response_metadata&, common::v1::ResponseMetadata*) const; +}; + +template <> +struct from_proto { + response_metadata operator()(const common::v1::ResponseMetadata*) const; +}; + +} // namespace proto_convert_details std::vector string_to_bytes(std::string const& s); std::string bytes_to_string(std::vector const& b); -std::chrono::microseconds from_proto(const google::protobuf::Duration& proto); -google::protobuf::Duration to_proto(std::chrono::microseconds duration); - // the authority on a grpc::ClientContext is sometimes set to an invalid uri on mac, causing // `rust-utils` to fail to process gRPC requests. This class provides a convenience wrapper around a // grpc ClientContext that allows us to make any necessary modifications to authority or else where @@ -49,14 +90,19 @@ google::protobuf::Duration to_proto(std::chrono::microseconds duration); class ClientContext { public: ClientContext(); + ~ClientContext(); + + void try_cancel(); + operator grpc::ClientContext*(); operator const grpc::ClientContext*() const; + void set_debug_key(const std::string& debug_key); private: void set_client_ctx_authority_(); void add_viam_client_version_(); - grpc::ClientContext wrapped_context_; + std::unique_ptr wrapped_context_; }; /// @brief Given a fully qualified resource name, returns remote name (or "" if no remote name diff --git a/src/viam/sdk/components/private/board_client.cpp b/src/viam/sdk/components/private/board_client.cpp index b6c6a952f..11af0428a 100644 --- a/src/viam/sdk/components/private/board_client.cpp +++ b/src/viam/sdk/components/private/board_client.cpp @@ -182,7 +182,7 @@ void BoardClient::set_power_mode(power_mode power_mode, [&](auto& request) { request.set_power_mode(to_proto(power_mode)); if (duration.has_value()) { - *request.mutable_duration() = ::viam::sdk::to_proto(duration.get()); + *request.mutable_duration() = v2::to_proto(duration.get()); } }) .invoke(); diff --git a/src/viam/sdk/components/private/board_server.cpp b/src/viam/sdk/components/private/board_server.cpp index b3064912a..9b7338d65 100644 --- a/src/viam/sdk/components/private/board_server.cpp +++ b/src/viam/sdk/components/private/board_server.cpp @@ -226,7 +226,7 @@ ::grpc::Status BoardServer::SetPowerMode( return make_service_helper( "BoardServer::SetPowerMode", this, request)([&](auto& helper, auto& board) { if (request->has_duration()) { - auto duration = ::viam::sdk::from_proto(request->duration()); + auto duration = v2::from_proto(request->duration()); board->set_power_mode(from_proto(request->power_mode()), helper.getExtra(), duration); } else { board->set_power_mode(from_proto(request->power_mode()), helper.getExtra()); diff --git a/src/viam/sdk/components/private/camera_client.cpp b/src/viam/sdk/components/private/camera_client.cpp index eb2e24ced..0818bfb39 100644 --- a/src/viam/sdk/components/private/camera_client.cpp +++ b/src/viam/sdk/components/private/camera_client.cpp @@ -56,7 +56,7 @@ Camera::image_collection from_proto(const viam::component::camera::v1::GetImages images.push_back(raw_image); } image_collection.images = std::move(images); - image_collection.metadata = response_metadata::from_proto(proto.response_metadata()); + image_collection.metadata = v2::from_proto(proto.response_metadata()); return image_collection; } diff --git a/src/viam/sdk/components/private/camera_server.cpp b/src/viam/sdk/components/private/camera_server.cpp index eb3532814..ab4b65179 100644 --- a/src/viam/sdk/components/private/camera_server.cpp +++ b/src/viam/sdk/components/private/camera_server.cpp @@ -94,7 +94,7 @@ ::grpc::Status CameraServer::GetImages( proto_image.set_image(img_string); *response->mutable_images()->Add() = std::move(proto_image); } - *response->mutable_response_metadata() = response_metadata::to_proto(image_coll.metadata); + *response->mutable_response_metadata() = v2::to_proto(image_coll.metadata); }); } diff --git a/src/viam/sdk/config/resource.cpp b/src/viam/sdk/config/resource.cpp index ed772a328..45402166a 100644 --- a/src/viam/sdk/config/resource.cpp +++ b/src/viam/sdk/config/resource.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -18,6 +19,26 @@ namespace viam { namespace sdk { +ResourceConfig::ResourceConfig(std::string type, + std::string name, + std::string namespace_, + ProtoStruct attributes, + std::string api, + Model model, + LinkConfig frame) + : api_({kRDK, type, ""}), + frame_(std::move(frame)), + model_(std::move(model)), + name_(std::move(name)), + namespace__(std::move(namespace_)), + type_(std::move(type)), + attributes_(std::move(attributes)) { + if (api.find(':') != std::string::npos) { + api_ = API::from_string(std::move(api)); + } + fix_api(); +} + ResourceConfig::ResourceConfig(std::string type) : api_({kRDK, type, ""}), type_(std::move(type)) {} Name ResourceConfig::resource_name() { @@ -59,6 +80,14 @@ const std::string& ResourceConfig::type() const { return type_; } +const std::vector& viam::sdk::ResourceConfig::depends_on() const { + return depends_on_; +} + +const std::vector& viam::sdk::ResourceConfig::service_config() const { + return service_config_; +} + const ProtoStruct& ResourceConfig::attributes() const { return attributes_; } @@ -91,54 +120,42 @@ void ResourceConfig::fix_api() { } } -ResourceConfig ResourceConfig::from_proto(const viam::app::v1::ComponentConfig& proto_cfg) { - ResourceConfig resource(proto_cfg.type()); - resource.name_ = proto_cfg.name(); - resource.namespace__ = proto_cfg.namespace_(); - resource.type_ = proto_cfg.type(); - resource.attributes_ = v2::from_proto(proto_cfg.attributes()); - const std::string& api = proto_cfg.api(); - if (api.find(':') != std::string::npos) { - resource.api_ = API::from_string(api); - } - resource.model_ = Model::from_str(proto_cfg.model()); +namespace proto_convert_details { - resource.fix_api(); - - if (proto_cfg.has_frame()) { - resource.frame_ = v2::from_proto(proto_cfg.frame()); - } +void to_proto::operator()( + const ResourceLevelServiceConfig& self, app::v1::ResourceLevelServiceConfig* proto) const { + *proto->mutable_type() = self.type; + *proto->mutable_attributes() = v2::to_proto(self.attributes); +} - return resource; -}; +void to_proto::operator()(const ResourceConfig& self, + app::v1::ComponentConfig* proto) const { + *proto->mutable_service_configs() = impl::to_repeated_field(self.service_config()); -viam::app::v1::ComponentConfig ResourceConfig::to_proto() const { - viam::app::v1::ComponentConfig proto_cfg; - const google::protobuf::Struct s = v2::to_proto(attributes_); - const google::protobuf::RepeatedPtrField - service_configs; + *proto->mutable_name() = self.name(); + *proto->mutable_namespace_() = self.namespace_(); + *proto->mutable_type() = self.type(); + *proto->mutable_api() = self.api().to_string(); + *proto->mutable_model() = self.model().to_string(); + *proto->mutable_attributes() = v2::to_proto(self.attributes()); - for (const auto& svc_cfg : service_config_) { - viam::app::v1::ResourceLevelServiceConfig cfg; - *cfg.mutable_type() = svc_cfg.type; - *cfg.mutable_attributes() = v2::to_proto(svc_cfg.attributes); - *proto_cfg.mutable_service_configs()->Add() = cfg; - } + *proto->mutable_depends_on() = ::google::protobuf::RepeatedPtrField( + self.depends_on().begin(), self.depends_on().end()); - *proto_cfg.mutable_name() = name_; - *proto_cfg.mutable_namespace_() = namespace__; - *proto_cfg.mutable_type() = type_; - *proto_cfg.mutable_api() = api_.to_string(); - const std::string mm = model_.to_string(); - *proto_cfg.mutable_model() = mm; - *proto_cfg.mutable_attributes() = v2::to_proto(attributes_); - for (const auto& dep : depends_on_) { - *proto_cfg.mutable_depends_on()->Add() = dep; - } - *proto_cfg.mutable_frame() = v2::to_proto(frame_); + *proto->mutable_frame() = v2::to_proto(self.frame()); +} - return proto_cfg; +ResourceConfig from_proto::operator()( + const app::v1::ComponentConfig* proto) const { + return ResourceConfig(proto->type(), + proto->name(), + proto->namespace_(), + v2::from_proto(proto->attributes()), + proto->api(), + Model::from_str(proto->model()), + proto->has_frame() ? v2::from_proto(proto->frame()) : LinkConfig{}); } +} // namespace proto_convert_details } // namespace sdk } // namespace viam diff --git a/src/viam/sdk/config/resource.hpp b/src/viam/sdk/config/resource.hpp index a89ff0f9e..4fcaf1725 100644 --- a/src/viam/sdk/config/resource.hpp +++ b/src/viam/sdk/config/resource.hpp @@ -3,18 +3,26 @@ #include #include -#include -#include - +#include #include #include #include +namespace viam { +namespace app { +namespace v1 { + +class ComponentConfig; +class ResourceLevelServiceConfig; + +} // namespace v1 +} // namespace app +} // namespace viam + namespace viam { namespace sdk { -class ResourceLevelServiceConfig { - public: +struct ResourceLevelServiceConfig { std::string type; ProtoStruct attributes; ProtoValue converted_attributes; @@ -22,9 +30,16 @@ class ResourceLevelServiceConfig { class ResourceConfig { public: - static ResourceConfig from_proto(const viam::app::v1::ComponentConfig& proto_cfg); - viam::app::v1::ComponentConfig to_proto() const; + ResourceConfig(std::string type, + std::string name, + std::string namespace_, + ProtoStruct attributes, + std::string api, + Model model, + LinkConfig frame); + ResourceConfig(std::string type); + Name resource_name(); const API& api() const; const LinkConfig& frame() const; @@ -32,6 +47,8 @@ class ResourceConfig { const std::string& name() const; const std::string& namespace_() const; const std::string& type() const; + const std::vector& depends_on() const; + const std::vector& service_config() const; const ProtoStruct& attributes() const; private: @@ -49,5 +66,24 @@ class ResourceConfig { void fix_api(); }; +namespace proto_convert_details { + +template <> +struct to_proto { + void operator()(const ResourceLevelServiceConfig&, app::v1::ResourceLevelServiceConfig*) const; +}; + +template <> +struct to_proto { + void operator()(const ResourceConfig&, app::v1::ComponentConfig*) const; +}; + +template <> +struct from_proto { + ResourceConfig operator()(const app::v1::ComponentConfig*) const; +}; + +} // namespace proto_convert_details + } // namespace sdk } // namespace viam diff --git a/src/viam/sdk/module/handler_map.cpp b/src/viam/sdk/module/handler_map.cpp index d6e5fe0ed..2878c4361 100644 --- a/src/viam/sdk/module/handler_map.cpp +++ b/src/viam/sdk/module/handler_map.cpp @@ -24,7 +24,7 @@ viam::module::v1::HandlerMap HandlerMap_::to_proto() const { } viam::robot::v1::ResourceRPCSubtype rpc_subtype; const Name name(h.first.api(), "", ""); - const viam::common::v1::ResourceName resource_name = name.to_proto(); + const viam::common::v1::ResourceName resource_name = v2::to_proto(name); *rpc_subtype.mutable_subtype() = resource_name; *rpc_subtype.mutable_proto_service() = h.first.proto_service_name(); *hd.mutable_subtype() = rpc_subtype; @@ -34,7 +34,7 @@ viam::module::v1::HandlerMap HandlerMap_::to_proto() const { return proto; }; -HandlerMap_::HandlerMap_(){}; +HandlerMap_::HandlerMap_() {} // NOLINTNEXTLINE(readability-const-return-type) const HandlerMap_ HandlerMap_::from_proto(const viam::module::v1::HandlerMap& proto) { diff --git a/src/viam/sdk/module/service.cpp b/src/viam/sdk/module/service.cpp index b1bad21ac..430fbf2b7 100644 --- a/src/viam/sdk/module/service.cpp +++ b/src/viam/sdk/module/service.cpp @@ -73,7 +73,7 @@ ::grpc::Status ModuleService::AddResource(::grpc::ServerContext*, const ::viam::module::v1::AddResourceRequest* request, ::viam::module::v1::AddResourceResponse*) { const viam::app::v1::ComponentConfig& proto = request->config(); - const ResourceConfig cfg = ResourceConfig::from_proto(proto); + const ResourceConfig cfg = v2::from_proto(proto); const std::lock_guard lock(lock_); std::shared_ptr res; @@ -101,7 +101,7 @@ ::grpc::Status ModuleService::ReconfigureResource( const ::viam::module::v1::ReconfigureResourceRequest* request, ::viam::module::v1::ReconfigureResourceResponse*) { const viam::app::v1::ComponentConfig& proto = request->config(); - ResourceConfig cfg = ResourceConfig::from_proto(proto); + ResourceConfig cfg = v2::from_proto(proto); const Dependencies deps = get_dependencies_(request->dependencies(), cfg.name()); @@ -150,7 +150,7 @@ ::grpc::Status ModuleService::ValidateConfig( const ::viam::module::v1::ValidateConfigRequest* request, ::viam::module::v1::ValidateConfigResponse* response) { const viam::app::v1::ComponentConfig& proto = request->config(); - ResourceConfig cfg = ResourceConfig::from_proto(proto); + ResourceConfig cfg = v2::from_proto(proto); const std::shared_ptr reg = Registry::lookup_model(cfg.api(), cfg.model()); diff --git a/src/viam/sdk/resource/resource_api.cpp b/src/viam/sdk/resource/resource_api.cpp index 3cca16d0e..06eadc248 100644 --- a/src/viam/sdk/resource/resource_api.cpp +++ b/src/viam/sdk/resource/resource_api.cpp @@ -86,6 +86,9 @@ bool API::is_component_type() { return (this->resource_type() == "component"); } +Name::Name(API api, std::string remote, std::string name) + : api_(std::move(api)), remote_name_(std::move(remote)), name_(std::move(name)) {} + const API& Name::api() const { return api_; } @@ -112,26 +115,6 @@ std::string Name::short_name() const { return name_; } -viam::common::v1::ResourceName Name::to_proto() const { - viam::common::v1::ResourceName rn; - *rn.mutable_namespace_() = this->api().type_namespace(); - if (this->remote_name().empty()) { - *rn.mutable_name() = this->name(); - } else { - *rn.mutable_name() = this->remote_name() + ":" + this->name(); - } - *rn.mutable_type() = this->api().resource_type(); - *rn.mutable_subtype() = this->api().resource_subtype(); - return rn; -} - -Name Name::from_proto(const viam::common::v1::ResourceName& proto) { - auto name_parts = long_name_to_remote_and_short(proto.name()); - - return Name( - {proto.namespace_(), proto.type(), proto.subtype()}, name_parts.first, name_parts.second); -}; - Name Name::from_string(std::string name) { if (!std::regex_match(name, NAME_REGEX)) { throw Exception("Received invalid Name string: " + name); @@ -153,8 +136,28 @@ Name Name::from_string(std::string name) { return Name(api, remote, resource_name); } -Name::Name(API api, std::string remote, std::string name) - : api_(std::move(api)), remote_name_(std::move(remote)), name_(std::move(name)) {} +namespace proto_convert_details { + +void to_proto::operator()(const Name& self, common::v1::ResourceName* proto) const { + *proto->mutable_namespace_() = self.api().type_namespace(); + if (self.remote_name().empty()) { + *proto->mutable_name() = self.name(); + } else { + *proto->mutable_name() = self.remote_name() + ":" + self.name(); + } + *proto->mutable_type() = self.api().resource_type(); + *proto->mutable_subtype() = self.api().resource_subtype(); +} + +Name from_proto::operator()(const common::v1::ResourceName* proto) const { + auto name_parts = long_name_to_remote_and_short(proto->name()); + + return Name({proto->namespace_(), proto->type(), proto->subtype()}, + name_parts.first, + name_parts.second); +} + +} // namespace proto_convert_details bool operator==(const API& lhs, const API& rhs) { return lhs.to_string() == rhs.to_string(); diff --git a/src/viam/sdk/resource/resource_api.hpp b/src/viam/sdk/resource/resource_api.hpp index 5677a8fd4..9a87cf6b4 100644 --- a/src/viam/sdk/resource/resource_api.hpp +++ b/src/viam/sdk/resource/resource_api.hpp @@ -4,7 +4,17 @@ #include -#include +#include + +namespace viam { +namespace common { +namespace v1 { + +class ResourceName; + +} +} // namespace common +} // namespace viam namespace viam { namespace sdk { @@ -13,8 +23,9 @@ namespace sdk { /// @brief Defines a resource's namespace (e.g., `RDK`) and type (e.g., component or service). class APIType { public: + APIType() = default; APIType(std::string namespace_, std::string resource_type); - APIType(){}; + virtual std::string to_string() const; const std::string& type_namespace() const; @@ -30,13 +41,16 @@ class APIType { /// @class API /// @brief Extends `APIType` to additionally define a resource's subtype (e.g., `camera`). +// TODO: Maybe just merge these two classes or at least use composition rather than inheritance class API : public APIType { public: - virtual std::string to_string() const override; - API(){}; + static API from_string(std::string api); + + API() = default; API(std::string namespace_, std::string resource_type, std::string resource_subtype); API(APIType type, std::string resource_subtype); - static API from_string(std::string api); + + virtual std::string to_string() const override; const std::string& resource_subtype() const; void set_resource_subtype(const std::string& subtype); @@ -62,16 +76,18 @@ class API : public APIType { /// @brief A name for specific instances of resources. class Name { public: - std::string short_name() const; - std::string to_string() const; - viam::common::v1::ResourceName to_proto() const; - static Name from_proto(const viam::common::v1::ResourceName& proto); static Name from_string(std::string name); + Name(API api, std::string remote_name, std::string name); - Name(){}; + Name() = default; + + std::string short_name() const; + std::string to_string() const; + const API& api() const; const std::string& name() const; const std::string& remote_name() const; + friend bool operator==(const Name& lhs, const Name& rhs); friend std::ostream& operator<<(std::ostream& os, const Name& v); @@ -81,6 +97,20 @@ class Name { std::string name_; }; +namespace proto_convert_details { + +template <> +struct to_proto { + void operator()(const Name&, common::v1::ResourceName*) const; +}; + +template <> +struct from_proto { + Name operator()(const common::v1::ResourceName*) const; +}; + +} // namespace proto_convert_details + class RPCSubtype { public: bool operator<(const RPCSubtype& rhs) const { diff --git a/src/viam/sdk/resource/resource_manager.hpp b/src/viam/sdk/resource/resource_manager.hpp index 3bc894f49..b4dbb0e5d 100644 --- a/src/viam/sdk/resource/resource_manager.hpp +++ b/src/viam/sdk/resource/resource_manager.hpp @@ -9,9 +9,6 @@ #include #include -#include - -#include #include #include @@ -23,6 +20,8 @@ namespace sdk { /// @brief Defines a resource manager for use by anything that tracks resources. class ResourceManager { public: + ResourceManager() = default; + /// @brief Returns a resource. /// @param name the name of the desired resource. /// @throws `Exception` if the desired resource does not exist. @@ -63,8 +62,6 @@ class ResourceManager { /// @brief Returns a reference to the existing resources within the manager. const std::unordered_map>& resources() const; - ResourceManager(){}; - private: std::mutex lock_; std::unordered_map> resources_; diff --git a/src/viam/sdk/robot/client.cpp b/src/viam/sdk/robot/client.cpp index 0c3fc1824..3fe5d4d1f 100644 --- a/src/viam/sdk/robot/client.cpp +++ b/src/viam/sdk/robot/client.cpp @@ -90,7 +90,7 @@ RobotClient::operation from_proto(const Operation& proto) { op.arguments = v2::from_proto(proto.arguments()); } if (proto.has_started()) { - op.started = timestamp_to_time_pt(proto.started()); + op.started = v2::from_proto(proto.started()); } return op; } @@ -203,7 +203,7 @@ void RobotClient::refresh() { std::unordered_map> new_resources; std::vector current_resources; for (const auto& name : resp.resources()) { - current_resources.push_back(Name::from_proto(name)); + current_resources.push_back(v2::from_proto(name)); if (name.subtype() == "remote") { continue; } @@ -404,7 +404,7 @@ void RobotClient::stop_all(const std::unordered_map& extra) { const ProtoStruct& params = xtra.second; const google::protobuf::Struct s = v2::to_proto(params); viam::robot::v1::StopExtraParameters stop; - *stop.mutable_name() = name.to_proto(); + *stop.mutable_name() = v2::to_proto(name); *stop.mutable_params() = s; *ep->Add() = stop; } diff --git a/src/viam/sdk/robot/service.cpp b/src/viam/sdk/robot/service.cpp index 2ebdf2a9a..a841e9e5b 100644 --- a/src/viam/sdk/robot/service.cpp +++ b/src/viam/sdk/robot/service.cpp @@ -66,7 +66,7 @@ std::vector RobotService_::generate_metadata_() { std::vector metadata; for (const auto& key_and_val : resource_manager()->resources()) { for (const Name& name : registered_models_for_resource(key_and_val.second)) { - metadata.push_back(name.to_proto()); + metadata.push_back(v2::to_proto(name)); } } return metadata; @@ -104,7 +104,7 @@ ::grpc::Status RobotService_::StopAll(::grpc::ServerContext*, for (const auto& r : resource_manager()->resources()) { const std::shared_ptr resource = r.second; - const ResourceName rn = resource->get_resource_name().to_proto(); + const ResourceName rn = v2::to_proto(resource->get_resource_name()); const std::string rn_ = rn.SerializeAsString(); if (extra.find(rn_) != extra.end()) { try { diff --git a/src/viam/sdk/services/private/motion_client.cpp b/src/viam/sdk/services/private/motion_client.cpp index 115fd5280..9252e9c60 100644 --- a/src/viam/sdk/services/private/motion_client.cpp +++ b/src/viam/sdk/services/private/motion_client.cpp @@ -19,8 +19,8 @@ namespace impl { service::motion::v1::ObstacleDetector to_proto(const obstacle_detector& od) { service::motion::v1::ObstacleDetector proto; - *proto.mutable_vision_service() = od.vision_service.to_proto(); - *proto.mutable_camera() = od.camera.to_proto(); + *proto.mutable_vision_service() = v2::to_proto(od.vision_service); + *proto.mutable_camera() = v2::to_proto(od.camera); return proto; } @@ -109,7 +109,7 @@ Motion::plan_status from_proto(const service::motion::v1::PlanStatus& proto) { if (proto.has_reason()) { mps.reason = proto.reason(); } - mps.timestamp = timestamp_to_time_pt(proto.timestamp()); + mps.timestamp = v2::from_proto(proto.timestamp()); return mps; } @@ -127,7 +127,7 @@ std::vector from_proto( Motion::plan_status_with_id from_proto(const service::motion::v1::PlanStatusWithID& proto) { Motion::plan_status_with_id pswi; pswi.execution_id = proto.execution_id(); - pswi.component_name = Name::from_proto(proto.component_name()); + pswi.component_name = v2::from_proto(proto.component_name()); pswi.plan_id = proto.plan_id(); pswi.status = from_proto(proto.status()); @@ -153,7 +153,7 @@ Motion::plan plan_from_proto(const service::motion::v1::Plan& proto) { Motion::plan plan; plan.id = proto.id(); plan.execution_id = proto.execution_id(); - plan.component_name = Name::from_proto(proto.component_name()); + plan.component_name = v2::from_proto(proto.component_name()); plan.steps = steps_from_proto(proto.steps()); return plan; } @@ -189,7 +189,7 @@ bool MotionClient::move(const pose_in_frame& destination, return make_client_helper(this, *stub_, &StubType::Move) .with(extra, [&](auto& request) { - *request.mutable_component_name() = component_name.to_proto(); + *request.mutable_component_name() = v2::to_proto(component_name); *request.mutable_destination() = v2::to_proto(destination); if (constraints) { *request.mutable_constraints() = to_proto(*constraints); @@ -212,8 +212,8 @@ std::string MotionClient::move_on_map( .with(extra, [&](auto& request) { *request.mutable_destination() = v2::to_proto(destination); - *request.mutable_component_name() = component_name.to_proto(); - *request.mutable_slam_service_name() = slam_name.to_proto(); + *request.mutable_component_name() = v2::to_proto(component_name); + *request.mutable_slam_service_name() = v2::to_proto(slam_name); for (const auto& obstacle : obstacles) { *request.mutable_obstacles()->Add() = v2::to_proto(obstacle); @@ -239,8 +239,8 @@ std::string MotionClient::move_on_globe( .with(extra, [&](auto& request) { *request.mutable_destination() = v2::to_proto(destination); - *request.mutable_component_name() = component_name.to_proto(); - *request.mutable_movement_sensor_name() = movement_sensor_name.to_proto(); + *request.mutable_component_name() = v2::to_proto(component_name); + *request.mutable_movement_sensor_name() = v2::to_proto(movement_sensor_name); if (heading && !isnan(*heading)) { request.set_heading(*heading); @@ -265,7 +265,7 @@ pose_in_frame MotionClient::get_pose( return make_client_helper(this, *stub_, &StubType::GetPose) .with(extra, [&](auto& request) { - *request.mutable_component_name() = component_name.to_proto(); + *request.mutable_component_name() = v2::to_proto(component_name); *request.mutable_destination_frame() = destination_frame; *request.mutable_supplemental_transforms() = impl::to_repeated_field(supplemental_transforms); @@ -275,7 +275,7 @@ pose_in_frame MotionClient::get_pose( void MotionClient::stop_plan(const Name& name, const ProtoStruct& extra) { return make_client_helper(this, *stub_, &StubType::StopPlan) - .with(extra, [&](auto& request) { *request.mutable_component_name() = name.to_proto(); }) + .with(extra, [&](auto& request) { *request.mutable_component_name() = v2::to_proto(name); }) .invoke(); } @@ -287,7 +287,7 @@ std::pair> Motio return make_client_helper(this, *stub_, &StubType::GetPlan) .with(extra, [&](auto& request) { - *request.mutable_component_name() = component_name.to_proto(); + *request.mutable_component_name() = v2::to_proto(component_name); request.set_last_plan_only(last_plan_only); if (execution_id) { *request.mutable_execution_id() = *execution_id; diff --git a/src/viam/sdk/services/private/motion_server.cpp b/src/viam/sdk/services/private/motion_server.cpp index a703ba587..eee9360cf 100644 --- a/src/viam/sdk/services/private/motion_server.cpp +++ b/src/viam/sdk/services/private/motion_server.cpp @@ -39,7 +39,7 @@ service::motion::v1::PlanState to_proto(const Motion::plan_state& state) { service::motion::v1::PlanStatus to_proto(const Motion::plan_status& ps) { service::motion::v1::PlanStatus proto; - *proto.mutable_timestamp() = time_pt_to_timestamp(ps.timestamp); + *proto.mutable_timestamp() = v2::to_proto(ps.timestamp); if (ps.reason) { *proto.mutable_reason() = *ps.reason; } @@ -62,7 +62,7 @@ service::motion::v1::PlanStep to_proto(const Motion::steps::step& step) { service::motion::v1::Plan to_proto(const Motion::plan& plan) { service::motion::v1::Plan proto; *proto.mutable_id() = plan.id; - *proto.mutable_component_name() = plan.component_name.to_proto(); + *proto.mutable_component_name() = v2::to_proto(plan.component_name); *proto.mutable_execution_id() = plan.execution_id; for (const auto& step : plan.steps.steps) { *proto.mutable_steps()->Add() = to_proto(step); @@ -86,7 +86,7 @@ service::motion::v1::PlanStatusWithID to_proto(const Motion::plan_status_with_id service::motion::v1::PlanStatusWithID proto; *proto.mutable_execution_id() = pswi.execution_id; - *proto.mutable_component_name() = pswi.component_name.to_proto(); + *proto.mutable_component_name() = v2::to_proto(pswi.component_name); *proto.mutable_plan_id() = pswi.plan_id; *proto.mutable_status() = to_proto(pswi.status); @@ -95,8 +95,8 @@ service::motion::v1::PlanStatusWithID to_proto(const Motion::plan_status_with_id obstacle_detector from_proto(const service::motion::v1::ObstacleDetector& proto) { obstacle_detector oc; - oc.vision_service = Name::from_proto(proto.vision_service()); - oc.camera = Name::from_proto(proto.camera()); + oc.vision_service = v2::from_proto(proto.vision_service()); + oc.camera = v2::from_proto(proto.camera()); return oc; } @@ -187,7 +187,7 @@ ::grpc::Status MotionServer::Move(::grpc::ServerContext*, } const bool success = motion->move(v2::from_proto(request->destination()), - Name::from_proto(request->component_name()), + v2::from_proto(request->component_name()), std::move(ws), std::move(constraints), helper.getExtra()); @@ -202,8 +202,8 @@ ::grpc::Status MotionServer::MoveOnMap( return make_service_helper( "MotionServer::MoveOnMap", this, request)([&](auto& helper, auto& motion) { const auto destination = v2::from_proto(request->destination()); - const auto component_name = Name::from_proto(request->component_name()); - const auto slam_name = Name::from_proto(request->slam_service_name()); + const auto component_name = v2::from_proto(request->component_name()); + const auto slam_name = v2::from_proto(request->slam_service_name()); std::shared_ptr mc; if (request->has_motion_configuration()) { @@ -230,8 +230,8 @@ ::grpc::Status MotionServer::MoveOnGlobe( return make_service_helper( "MotionServer::MoveOnGlobe", this, request)([&](auto& helper, auto& motion) { const auto destination = v2::from_proto(request->destination()); - const auto component_name = Name::from_proto(request->component_name()); - const auto movement_sensor_name = Name::from_proto(request->movement_sensor_name()); + const auto component_name = v2::from_proto(request->component_name()); + const auto movement_sensor_name = v2::from_proto(request->movement_sensor_name()); const std::vector obstacles = impl::from_repeated_field(request->obstacles()); const std::vector bounding_regions = impl::from_repeated_field(request->bounding_regions()); @@ -266,7 +266,7 @@ ::grpc::Status MotionServer::GetPose( ::viam::service::motion::v1::GetPoseResponse* response) noexcept { return make_service_helper( "MotionServer::GetPose", this, request)([&](auto& helper, auto& motion) { - const auto& component_name = Name::from_proto(request->component_name()); + const auto& component_name = v2::from_proto(request->component_name()); const std::string& destination_frame = request->destination_frame(); std::vector supplemental_transforms; for (const auto& proto_transform : request->supplemental_transforms()) { @@ -284,7 +284,7 @@ ::grpc::Status MotionServer::GetPlan( ::viam::service::motion::v1::GetPlanResponse* response) noexcept { return make_service_helper( "MotionServer::GetPlan", this, request)([&](auto& helper, auto& motion) { - const auto& component_name = Name::from_proto(request->component_name()); + const auto& component_name = v2::from_proto(request->component_name()); Motion::plan_with_status plan; std::vector replan_history; const bool last_plan_only(request->last_plan_only()); @@ -337,7 +337,7 @@ ::grpc::Status MotionServer::StopPlan(::grpc::ServerContext*, ::viam::service::motion::v1::StopPlanResponse*) noexcept { return make_service_helper( "MotionServer::StopPlan", this, request)([&](auto& helper, auto& motion) { - const auto& component_name = Name::from_proto(request->component_name()); + const auto& component_name = v2::from_proto(request->component_name()); motion->stop_plan(component_name, helper.getExtra()); }); diff --git a/src/viam/sdk/tests/test_common.cpp b/src/viam/sdk/tests/test_common.cpp index 6e4454b03..ca4b87398 100644 --- a/src/viam/sdk/tests/test_common.cpp +++ b/src/viam/sdk/tests/test_common.cpp @@ -2,6 +2,8 @@ #include +#include + #include #include @@ -24,9 +26,9 @@ BOOST_AUTO_TEST_CASE(test_zero) { Duration input; input.set_nanos(0); input.set_seconds(0); - auto converted = from_proto(input); + auto converted = v2::from_proto(input); BOOST_CHECK_EQUAL(converted.count(), 0); - auto reconverted = to_proto(converted); + auto reconverted = v2::to_proto(converted); BOOST_CHECK_EQUAL(reconverted.nanos(), 0); BOOST_CHECK_EQUAL(reconverted.seconds(), 0); } @@ -35,9 +37,9 @@ BOOST_AUTO_TEST_CASE(test_rounding_negative) { Duration input; input.set_nanos(-100); input.set_seconds(0); - auto converted = from_proto(input); + auto converted = v2::from_proto(input); BOOST_CHECK_EQUAL(converted.count(), -1); - auto reconverted = to_proto(converted); + auto reconverted = v2::to_proto(converted); BOOST_CHECK_EQUAL(reconverted.nanos(), -1000); BOOST_CHECK_EQUAL(reconverted.seconds(), 0); } @@ -46,9 +48,9 @@ BOOST_AUTO_TEST_CASE(test_rounding_positive) { Duration input; input.set_nanos(999); input.set_seconds(0); - auto converted = from_proto(input); + auto converted = v2::from_proto(input); BOOST_CHECK_EQUAL(converted.count(), 1); - auto reconverted = to_proto(converted); + auto reconverted = v2::to_proto(converted); BOOST_CHECK_EQUAL(reconverted.nanos(), 1000); BOOST_CHECK_EQUAL(reconverted.seconds(), 0); } @@ -58,9 +60,9 @@ BOOST_AUTO_TEST_CASE(test_mixed_sign_rounding) { // Should round to -1 μs input.set_nanos(-500); input.set_seconds(1); - auto converted = from_proto(input); + auto converted = v2::from_proto(input); BOOST_CHECK_EQUAL(converted.count(), 1e6 - 1); - auto reconverted = to_proto(converted); + auto reconverted = v2::to_proto(converted); BOOST_CHECK_EQUAL(reconverted.nanos(), 1e9 - 1000); BOOST_CHECK_EQUAL(reconverted.seconds(), 0); } @@ -70,9 +72,9 @@ BOOST_AUTO_TEST_CASE(test_medium_positive) { // Should round to 2 μs input.set_nanos(1500); input.set_seconds(1000); - auto converted = from_proto(input); + auto converted = v2::from_proto(input); BOOST_CHECK_EQUAL(converted.count(), 1000 * 1e6 + 2); - auto reconverted = to_proto(converted); + auto reconverted = v2::to_proto(converted); BOOST_CHECK_EQUAL(reconverted.nanos(), 2000); BOOST_CHECK_EQUAL(reconverted.seconds(), 1000); } @@ -85,9 +87,9 @@ BOOST_AUTO_TEST_CASE(test_large_positive) { // compliant with the proto spec int64_t max_seconds = 10e3 * 365 * 24 * 60 * 60; input.set_seconds(max_seconds); - auto converted = from_proto(input); + auto converted = v2::from_proto(input); BOOST_CHECK_EQUAL(converted.count(), 1e6 * max_seconds + 2); - auto reconverted = to_proto(converted); + auto reconverted = v2::to_proto(converted); BOOST_CHECK_EQUAL(reconverted.nanos(), 2000); BOOST_CHECK_EQUAL(reconverted.seconds(), max_seconds); } diff --git a/src/viam/sdk/tests/test_resource.cpp b/src/viam/sdk/tests/test_resource.cpp index db950355a..cba417847 100644 --- a/src/viam/sdk/tests/test_resource.cpp +++ b/src/viam/sdk/tests/test_resource.cpp @@ -2,6 +2,10 @@ #include #include + +#include +#include + #include #include #include @@ -52,7 +56,7 @@ BOOST_AUTO_TEST_CASE(test_name) { BOOST_CHECK_EQUAL(name1.name(), "name"); BOOST_CHECK_EQUAL(name1.short_name(), "remote:name"); BOOST_CHECK_EQUAL(name1.to_string(), "ns:service:st/remote:name"); - BOOST_CHECK_EQUAL(Name::from_proto(name1.to_proto()), name1); + BOOST_CHECK_EQUAL(v2::from_proto(v2::to_proto(name1)), name1); Name name2(API::from_string("ns:service:st"), "remote1:remote2", "name"); BOOST_CHECK_EQUAL(name2.api().to_string(), "ns:service:st"); @@ -60,7 +64,7 @@ BOOST_AUTO_TEST_CASE(test_name) { BOOST_CHECK_EQUAL(name2.name(), "name"); BOOST_CHECK_EQUAL(name2.short_name(), "remote1:remote2:name"); BOOST_CHECK_EQUAL(name2.to_string(), "ns:service:st/remote1:remote2:name"); - BOOST_CHECK_EQUAL(Name::from_proto(name2.to_proto()), name2); + BOOST_CHECK_EQUAL(v2::from_proto(v2::to_proto(name2)), name2); Name name3 = Name::from_string("ns:component:st/name"); BOOST_CHECK_EQUAL(name3.api().to_string(), "ns:component:st"); @@ -68,7 +72,7 @@ BOOST_AUTO_TEST_CASE(test_name) { BOOST_CHECK_EQUAL(name3.name(), "name"); BOOST_CHECK_EQUAL(name3.short_name(), "name"); BOOST_CHECK_EQUAL(name3.to_string(), "ns:component:st/name"); - BOOST_CHECK_EQUAL(Name::from_proto(name3.to_proto()), name3); + BOOST_CHECK_EQUAL(v2::from_proto(v2::to_proto(name3)), name3); BOOST_CHECK_THROW(Name::from_string("ns:service:#st/remote:name"), Exception); } @@ -235,7 +239,7 @@ BOOST_AUTO_TEST_CASE(test_resource) { *frame.mutable_translation() = t; *proto_cfg.mutable_frame() = frame; - ResourceConfig resource2 = ResourceConfig::from_proto(proto_cfg); + ResourceConfig resource2 = v2::from_proto(proto_cfg); BOOST_CHECK_EQUAL(resource2.name(), "name"); BOOST_CHECK_EQUAL(resource2.namespace_(), "ns"); BOOST_CHECK_EQUAL(resource2.type(), "type"); @@ -252,7 +256,7 @@ BOOST_AUTO_TEST_CASE(test_resource) { BOOST_CHECK_EQUAL(value.number_value(), 1); *proto_cfg.mutable_api() = "ns:component:test"; - BOOST_CHECK_THROW(ResourceConfig::from_proto(proto_cfg), Exception); + BOOST_CHECK_THROW(v2::from_proto(proto_cfg), Exception); } } // namespace sdktests