diff --git a/cpp/dmi/commons.pb.cc b/cpp/dmi/commons.pb.cc
new file mode 100644
index 0000000..157ab04
--- /dev/null
+++ b/cpp/dmi/commons.pb.cc
@@ -0,0 +1,102 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/commons.proto
+
+#include "dmi/commons.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+
+namespace dmi {
+}  // namespace dmi
+void InitDefaults_dmi_2fcommons_2eproto() {
+}
+
+constexpr ::google::protobuf::Metadata* file_level_metadata_dmi_2fcommons_2eproto = nullptr;
+const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors_dmi_2fcommons_2eproto[2];
+constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_dmi_2fcommons_2eproto = nullptr;
+const ::google::protobuf::uint32 TableStruct_dmi_2fcommons_2eproto::offsets[1] = {};
+static constexpr ::google::protobuf::internal::MigrationSchema* schemas = nullptr;
+static constexpr ::google::protobuf::Message* const* file_default_instances = nullptr;
+
+::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_dmi_2fcommons_2eproto = {
+  {}, AddDescriptors_dmi_2fcommons_2eproto, "dmi/commons.proto", schemas,
+  file_default_instances, TableStruct_dmi_2fcommons_2eproto::offsets,
+  file_level_metadata_dmi_2fcommons_2eproto, 0, file_level_enum_descriptors_dmi_2fcommons_2eproto, file_level_service_descriptors_dmi_2fcommons_2eproto,
+};
+
+const char descriptor_table_protodef_dmi_2fcommons_2eproto[] =
+  "\n\021dmi/commons.proto\022\003dmi*\?\n\006Status\022\024\n\020UN"
+  "DEFINED_STATUS\020\000\022\r\n\tOK_STATUS\020\001\022\020\n\014ERROR"
+  "_STATUS\020\002*\?\n\010LogLevel\022\t\n\005TRACE\020\000\022\t\n\005DEBU"
+  "G\020\001\022\010\n\004INFO\020\002\022\010\n\004WARN\020\003\022\t\n\005ERROR\020\004B;Z9gi"
+  "thub.com/opencord/device-management-inte"
+  "rface/v3/go/dmib\006proto3"
+  ;
+::google::protobuf::internal::DescriptorTable descriptor_table_dmi_2fcommons_2eproto = {
+  false, InitDefaults_dmi_2fcommons_2eproto, 
+  descriptor_table_protodef_dmi_2fcommons_2eproto,
+  "dmi/commons.proto", &assign_descriptors_table_dmi_2fcommons_2eproto, 223,
+};
+
+void AddDescriptors_dmi_2fcommons_2eproto() {
+  static constexpr ::google::protobuf::internal::InitFunc deps[1] =
+  {
+  };
+ ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fcommons_2eproto, deps, 0);
+}
+
+// Force running AddDescriptors() at dynamic initialization time.
+static bool dynamic_init_dummy_dmi_2fcommons_2eproto = []() { AddDescriptors_dmi_2fcommons_2eproto(); return true; }();
+namespace dmi {
+const ::google::protobuf::EnumDescriptor* Status_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fcommons_2eproto);
+  return file_level_enum_descriptors_dmi_2fcommons_2eproto[0];
+}
+bool Status_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+      return true;
+    default:
+      return false;
+  }
+}
+
+const ::google::protobuf::EnumDescriptor* LogLevel_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fcommons_2eproto);
+  return file_level_enum_descriptors_dmi_2fcommons_2eproto[1];
+}
+bool LogLevel_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+#include <google/protobuf/port_undef.inc>
diff --git a/cpp/dmi/commons.pb.h b/cpp/dmi/commons.pb.h
new file mode 100644
index 0000000..6b10482
--- /dev/null
+++ b/cpp/dmi/commons.pb.h
@@ -0,0 +1,142 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/commons.proto
+
+#ifndef PROTOBUF_INCLUDED_dmi_2fcommons_2eproto
+#define PROTOBUF_INCLUDED_dmi_2fcommons_2eproto
+
+#include <limits>
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+#if PROTOBUF_VERSION < 3007000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3007000 < PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/port_undef.inc>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/inlined_string_field.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/generated_enum_reflection.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+#define PROTOBUF_INTERNAL_EXPORT_dmi_2fcommons_2eproto
+
+// Internal implementation detail -- do not use these members.
+struct TableStruct_dmi_2fcommons_2eproto {
+  static const ::google::protobuf::internal::ParseTableField entries[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::AuxillaryParseTableField aux[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::ParseTable schema[1]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
+  static const ::google::protobuf::uint32 offsets[];
+};
+void AddDescriptors_dmi_2fcommons_2eproto();
+namespace google {
+namespace protobuf {
+}  // namespace protobuf
+}  // namespace google
+namespace dmi {
+
+enum Status {
+  UNDEFINED_STATUS = 0,
+  OK_STATUS = 1,
+  ERROR_STATUS = 2,
+  Status_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  Status_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool Status_IsValid(int value);
+const Status Status_MIN = UNDEFINED_STATUS;
+const Status Status_MAX = ERROR_STATUS;
+const int Status_ARRAYSIZE = Status_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* Status_descriptor();
+inline const ::std::string& Status_Name(Status value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    Status_descriptor(), value);
+}
+inline bool Status_Parse(
+    const ::std::string& name, Status* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<Status>(
+    Status_descriptor(), name, value);
+}
+enum LogLevel {
+  TRACE = 0,
+  DEBUG = 1,
+  INFO = 2,
+  WARN = 3,
+  ERROR = 4,
+  LogLevel_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  LogLevel_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool LogLevel_IsValid(int value);
+const LogLevel LogLevel_MIN = TRACE;
+const LogLevel LogLevel_MAX = ERROR;
+const int LogLevel_ARRAYSIZE = LogLevel_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* LogLevel_descriptor();
+inline const ::std::string& LogLevel_Name(LogLevel value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    LogLevel_descriptor(), value);
+}
+inline bool LogLevel_Parse(
+    const ::std::string& name, LogLevel* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<LogLevel>(
+    LogLevel_descriptor(), name, value);
+}
+// ===================================================================
+
+
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace dmi
+
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::dmi::Status> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::Status>() {
+  return ::dmi::Status_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::LogLevel> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::LogLevel>() {
+  return ::dmi::LogLevel_descriptor();
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#include <google/protobuf/port_undef.inc>
+#endif  // PROTOBUF_INCLUDED_dmi_2fcommons_2eproto
diff --git a/cpp/dmi/hw.pb.cc b/cpp/dmi/hw.pb.cc
new file mode 100644
index 0000000..1b32844
--- /dev/null
+++ b/cpp/dmi/hw.pb.cc
@@ -0,0 +1,7832 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/hw.proto
+
+#include "dmi/hw.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_ContainerComponentAttributes_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_PortComponentAttributes_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_PsuComponentAttributes_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_TransceiverComponentsAttributes_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Uri_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Uuid_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_ComponentSensorData_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_ComponentState_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<9> scc_info_Component_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftimestamp_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto;
+namespace dmi {
+class UuidDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Uuid> _instance;
+} _Uuid_default_instance_;
+class HardwareIDDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<HardwareID> _instance;
+} _HardwareID_default_instance_;
+class UriDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Uri> _instance;
+} _Uri_default_instance_;
+class ComponentStateDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ComponentState> _instance;
+} _ComponentState_default_instance_;
+class ComponentSensorDataDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ComponentSensorData> _instance;
+} _ComponentSensorData_default_instance_;
+class PortComponentAttributesDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<PortComponentAttributes> _instance;
+} _PortComponentAttributes_default_instance_;
+class ContainerComponentAttributesDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ContainerComponentAttributes> _instance;
+} _ContainerComponentAttributes_default_instance_;
+class PsuComponentAttributesDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<PsuComponentAttributes> _instance;
+} _PsuComponentAttributes_default_instance_;
+class TransceiverComponentsAttributesDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<TransceiverComponentsAttributes> _instance;
+} _TransceiverComponentsAttributes_default_instance_;
+class ComponentDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Component> _instance;
+  const ::dmi::PortComponentAttributes* port_attr_;
+  const ::dmi::ContainerComponentAttributes* container_attr_;
+  const ::dmi::PsuComponentAttributes* psu_attr_;
+  const ::dmi::TransceiverComponentsAttributes* transceiver_attr_;
+} _Component_default_instance_;
+class HardwareDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Hardware> _instance;
+} _Hardware_default_instance_;
+class ModifiableComponentDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ModifiableComponent> _instance;
+} _ModifiableComponent_default_instance_;
+}  // namespace dmi
+static void InitDefaultsUuid_dmi_2fhw_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_Uuid_default_instance_;
+    new (ptr) ::dmi::Uuid();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::Uuid::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_Uuid_dmi_2fhw_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsUuid_dmi_2fhw_2eproto}, {}};
+
+static void InitDefaultsHardwareID_dmi_2fhw_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_HardwareID_default_instance_;
+    new (ptr) ::dmi::HardwareID();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::HardwareID::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_HardwareID_dmi_2fhw_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsHardwareID_dmi_2fhw_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsUri_dmi_2fhw_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_Uri_default_instance_;
+    new (ptr) ::dmi::Uri();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::Uri::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_Uri_dmi_2fhw_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsUri_dmi_2fhw_2eproto}, {}};
+
+static void InitDefaultsComponentState_dmi_2fhw_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ComponentState_default_instance_;
+    new (ptr) ::dmi::ComponentState();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ComponentState::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_ComponentState_dmi_2fhw_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsComponentState_dmi_2fhw_2eproto}, {
+      &scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto.base,}};
+
+static void InitDefaultsComponentSensorData_dmi_2fhw_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ComponentSensorData_default_instance_;
+    new (ptr) ::dmi::ComponentSensorData();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ComponentSensorData::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_ComponentSensorData_dmi_2fhw_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsComponentSensorData_dmi_2fhw_2eproto}, {
+      &scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto.base,}};
+
+static void InitDefaultsPortComponentAttributes_dmi_2fhw_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_PortComponentAttributes_default_instance_;
+    new (ptr) ::dmi::PortComponentAttributes();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::PortComponentAttributes::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_PortComponentAttributes_dmi_2fhw_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsPortComponentAttributes_dmi_2fhw_2eproto}, {}};
+
+static void InitDefaultsContainerComponentAttributes_dmi_2fhw_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ContainerComponentAttributes_default_instance_;
+    new (ptr) ::dmi::ContainerComponentAttributes();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ContainerComponentAttributes::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_ContainerComponentAttributes_dmi_2fhw_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsContainerComponentAttributes_dmi_2fhw_2eproto}, {}};
+
+static void InitDefaultsPsuComponentAttributes_dmi_2fhw_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_PsuComponentAttributes_default_instance_;
+    new (ptr) ::dmi::PsuComponentAttributes();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::PsuComponentAttributes::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_PsuComponentAttributes_dmi_2fhw_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsPsuComponentAttributes_dmi_2fhw_2eproto}, {}};
+
+static void InitDefaultsTransceiverComponentsAttributes_dmi_2fhw_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_TransceiverComponentsAttributes_default_instance_;
+    new (ptr) ::dmi::TransceiverComponentsAttributes();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::TransceiverComponentsAttributes::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_TransceiverComponentsAttributes_dmi_2fhw_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsTransceiverComponentsAttributes_dmi_2fhw_2eproto}, {}};
+
+static void InitDefaultsComponent_dmi_2fhw_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_Component_default_instance_;
+    new (ptr) ::dmi::Component();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::Component::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<9> scc_info_Component_dmi_2fhw_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 9, InitDefaultsComponent_dmi_2fhw_2eproto}, {
+      &scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto.base,
+      &scc_info_Uri_dmi_2fhw_2eproto.base,
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,
+      &scc_info_ComponentState_dmi_2fhw_2eproto.base,
+      &scc_info_ComponentSensorData_dmi_2fhw_2eproto.base,
+      &scc_info_PortComponentAttributes_dmi_2fhw_2eproto.base,
+      &scc_info_ContainerComponentAttributes_dmi_2fhw_2eproto.base,
+      &scc_info_PsuComponentAttributes_dmi_2fhw_2eproto.base,
+      &scc_info_TransceiverComponentsAttributes_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsHardware_dmi_2fhw_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_Hardware_default_instance_;
+    new (ptr) ::dmi::Hardware();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::Hardware::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_Hardware_dmi_2fhw_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsHardware_dmi_2fhw_2eproto}, {
+      &scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto.base,
+      &scc_info_Component_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsModifiableComponent_dmi_2fhw_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ModifiableComponent_default_instance_;
+    new (ptr) ::dmi::ModifiableComponent();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ModifiableComponent::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_ModifiableComponent_dmi_2fhw_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsModifiableComponent_dmi_2fhw_2eproto}, {
+      &scc_info_Component_dmi_2fhw_2eproto.base,
+      &scc_info_Uri_dmi_2fhw_2eproto.base,}};
+
+void InitDefaults_dmi_2fhw_2eproto() {
+  ::google::protobuf::internal::InitSCC(&scc_info_Uuid_dmi_2fhw_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_HardwareID_dmi_2fhw_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_Uri_dmi_2fhw_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ComponentState_dmi_2fhw_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ComponentSensorData_dmi_2fhw_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_PortComponentAttributes_dmi_2fhw_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ContainerComponentAttributes_dmi_2fhw_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_PsuComponentAttributes_dmi_2fhw_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_TransceiverComponentsAttributes_dmi_2fhw_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_Component_dmi_2fhw_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_Hardware_dmi_2fhw_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ModifiableComponent_dmi_2fhw_2eproto.base);
+}
+
+::google::protobuf::Metadata file_level_metadata_dmi_2fhw_2eproto[12];
+const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors_dmi_2fhw_2eproto[15];
+constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_dmi_2fhw_2eproto = nullptr;
+
+const ::google::protobuf::uint32 TableStruct_dmi_2fhw_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::Uuid, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::Uuid, uuid_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::HardwareID, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::HardwareID, uuid_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::Uri, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::Uri, uri_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentState, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentState, state_last_changed_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentState, admin_state_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentState, oper_state_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentState, usage_state_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentState, alarm_state_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentState, standby_state_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentSensorData, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentSensorData, value_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentSensorData, type_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentSensorData, scale_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentSensorData, precision_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentSensorData, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentSensorData, units_display_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentSensorData, timestamp_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentSensorData, value_update_rate_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ComponentSensorData, data_type_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::PortComponentAttributes, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::PortComponentAttributes, connector_type_),
+  PROTOBUF_FIELD_OFFSET(::dmi::PortComponentAttributes, speed_),
+  PROTOBUF_FIELD_OFFSET(::dmi::PortComponentAttributes, protocol_),
+  PROTOBUF_FIELD_OFFSET(::dmi::PortComponentAttributes, physical_label_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ContainerComponentAttributes, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ContainerComponentAttributes, physical_label_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::PsuComponentAttributes, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::PsuComponentAttributes, supported_voltage_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::TransceiverComponentsAttributes, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::TransceiverComponentsAttributes, form_factor_),
+  PROTOBUF_FIELD_OFFSET(::dmi::TransceiverComponentsAttributes, trans_type_),
+  PROTOBUF_FIELD_OFFSET(::dmi::TransceiverComponentsAttributes, max_distance_),
+  PROTOBUF_FIELD_OFFSET(::dmi::TransceiverComponentsAttributes, max_distance_scale_),
+  PROTOBUF_FIELD_OFFSET(::dmi::TransceiverComponentsAttributes, rx_wavelength_),
+  PROTOBUF_FIELD_OFFSET(::dmi::TransceiverComponentsAttributes, tx_wavelength_),
+  PROTOBUF_FIELD_OFFSET(::dmi::TransceiverComponentsAttributes, wavelength_scale_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, _internal_metadata_),
+  ~0u,  // no _extensions_
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, _oneof_case_[0]),
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, name_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, class__),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, description_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, parent_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, parent_rel_pos_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, children_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, hardware_rev_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, firmware_rev_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, software_rev_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, serial_num_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, mfg_name_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, model_name_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, alias_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, asset_id_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, is_fru_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, mfg_date_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, uri_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, state_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, sensor_data_),
+  offsetof(::dmi::ComponentDefaultTypeInternal, port_attr_),
+  offsetof(::dmi::ComponentDefaultTypeInternal, container_attr_),
+  offsetof(::dmi::ComponentDefaultTypeInternal, psu_attr_),
+  offsetof(::dmi::ComponentDefaultTypeInternal, transceiver_attr_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Component, specific_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::Hardware, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::Hardware, last_change_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Hardware, root_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Hardware, last_booted_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ModifiableComponent, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ModifiableComponent, name_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ModifiableComponent, class__),
+  PROTOBUF_FIELD_OFFSET(::dmi::ModifiableComponent, parent_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ModifiableComponent, parent_rel_pos_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ModifiableComponent, alias_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ModifiableComponent, asset_id_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ModifiableComponent, uri_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ModifiableComponent, admin_state_),
+};
+static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, -1, sizeof(::dmi::Uuid)},
+  { 6, -1, sizeof(::dmi::HardwareID)},
+  { 12, -1, sizeof(::dmi::Uri)},
+  { 18, -1, sizeof(::dmi::ComponentState)},
+  { 29, -1, sizeof(::dmi::ComponentSensorData)},
+  { 43, -1, sizeof(::dmi::PortComponentAttributes)},
+  { 52, -1, sizeof(::dmi::ContainerComponentAttributes)},
+  { 58, -1, sizeof(::dmi::PsuComponentAttributes)},
+  { 64, -1, sizeof(::dmi::TransceiverComponentsAttributes)},
+  { 76, -1, sizeof(::dmi::Component)},
+  { 106, -1, sizeof(::dmi::Hardware)},
+  { 114, -1, sizeof(::dmi::ModifiableComponent)},
+};
+
+static ::google::protobuf::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_Uuid_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_HardwareID_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_Uri_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ComponentState_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ComponentSensorData_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_PortComponentAttributes_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ContainerComponentAttributes_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_PsuComponentAttributes_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_TransceiverComponentsAttributes_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_Component_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_Hardware_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ModifiableComponent_default_instance_),
+};
+
+::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_dmi_2fhw_2eproto = {
+  {}, AddDescriptors_dmi_2fhw_2eproto, "dmi/hw.proto", schemas,
+  file_default_instances, TableStruct_dmi_2fhw_2eproto::offsets,
+  file_level_metadata_dmi_2fhw_2eproto, 12, file_level_enum_descriptors_dmi_2fhw_2eproto, file_level_service_descriptors_dmi_2fhw_2eproto,
+};
+
+const char descriptor_table_protodef_dmi_2fhw_2eproto[] =
+  "\n\014dmi/hw.proto\022\003dmi\032\037google/protobuf/tim"
+  "estamp.proto\"\024\n\004Uuid\022\014\n\004uuid\030\001 \001(\t\"%\n\nHa"
+  "rdwareID\022\027\n\004uuid\030\001 \001(\0132\t.dmi.Uuid\"\022\n\003Uri"
+  "\022\013\n\003uri\030\001 \001(\t\"\265\002\n\016ComponentState\0226\n\022stat"
+  "e_last_changed\030\001 \001(\0132\032.google.protobuf.T"
+  "imestamp\022-\n\013admin_state\030\002 \001(\0162\030.dmi.Comp"
+  "onentAdminState\022+\n\noper_state\030\003 \001(\0162\027.dm"
+  "i.ComponentOperState\022-\n\013usage_state\030\004 \001("
+  "\0162\030.dmi.ComponentUsageState\022-\n\013alarm_sta"
+  "te\030\005 \001(\0162\030.dmi.ComponentAlarmState\0221\n\rst"
+  "andby_state\030\006 \001(\0162\032.dmi.ComponentStandby"
+  "State\"\220\002\n\023ComponentSensorData\022\r\n\005value\030\001"
+  " \001(\005\022 \n\004type\030\002 \001(\0162\022.dmi.DataValueType\022\036"
+  "\n\005scale\030\003 \001(\0162\017.dmi.ValueScale\022\021\n\tprecis"
+  "ion\030\004 \001(\005\022!\n\006status\030\005 \001(\0162\021.dmi.SensorSt"
+  "atus\022\025\n\runits_display\030\006 \001(\t\022-\n\ttimestamp"
+  "\030\007 \001(\0132\032.google.protobuf.Timestamp\022\031\n\021va"
+  "lue_update_rate\030\010 \001(\r\022\021\n\tdata_type\030\t \001(\t"
+  "\"\202\005\n\027PortComponentAttributes\022B\n\016connecto"
+  "r_type\030\001 \001(\0162*.dmi.PortComponentAttribut"
+  "es.ConnectorType\0221\n\005speed\030\002 \001(\0162\".dmi.Po"
+  "rtComponentAttributes.Speed\0227\n\010protocol\030"
+  "\003 \001(\0162%.dmi.PortComponentAttributes.Prot"
+  "ocol\022\026\n\016physical_label\030\004 \001(\t\"p\n\rConnecto"
+  "rType\022\034\n\030CONNECTOR_TYPE_UNDEFINED\020\000\022\010\n\004R"
+  "J45\020\001\022\014\n\010FIBER_LC\020\002\022\017\n\013FIBER_SC_PC\020\003\022\r\n\t"
+  "FIBER_MPO\020\004\022\t\n\005RS232\020\005\"\256\001\n\005Speed\022\023\n\017SPEE"
+  "D_UNDEFINED\020\000\022\013\n\007DYNAMIC\020\001\022\r\n\tGIGABIT_1\020"
+  "\002\022\016\n\nGIGABIT_10\020\003\022\016\n\nGIGABIT_25\020\004\022\016\n\nGIG"
+  "ABIT_40\020\005\022\017\n\013GIGABIT_100\020\006\022\017\n\013GIGABIT_40"
+  "0\020\007\022\020\n\014MEGABIT_2500\020\010\022\020\n\014MEGABIT_1250\020\t\""
+  "|\n\010Protocol\022\026\n\022PROTOCOL_UNDEFINED\020\000\022\014\n\010E"
+  "THERNET\020\001\022\010\n\004GPON\020\002\022\t\n\005XGPON\020\003\022\n\n\006XGSPON"
+  "\020\004\022\t\n\005GFAST\020\005\022\n\n\006SERIAL\020\006\022\010\n\004EPON\020\007\022\010\n\004B"
+  "ITS\020\010\"6\n\034ContainerComponentAttributes\022\026\n"
+  "\016physical_label\030\001 \001(\t\"\263\001\n\026PsuComponentAt"
+  "tributes\022G\n\021supported_voltage\030\001 \001(\0162,.dm"
+  "i.PsuComponentAttributes.SupportedVoltag"
+  "e\"P\n\020SupportedVoltage\022\037\n\033SUPPORTED_VOLTA"
+  "GE_UNDEFINED\020\000\022\007\n\003V48\020\001\022\010\n\004V230\020\002\022\010\n\004V11"
+  "5\020\003\"\357\004\n\037TransceiverComponentsAttributes\022"
+  "D\n\013form_factor\030\001 \001(\0162/.dmi.TransceiverCo"
+  "mponentsAttributes.FormFactor\022=\n\ntrans_t"
+  "ype\030\002 \001(\0162).dmi.TransceiverComponentsAtt"
+  "ributes.Type\022\024\n\014max_distance\030\003 \001(\r\022+\n\022ma"
+  "x_distance_scale\030\004 \001(\0162\017.dmi.ValueScale\022"
+  "\025\n\rrx_wavelength\030\005 \003(\r\022\025\n\rtx_wavelength\030"
+  "\006 \003(\r\022)\n\020wavelength_scale\030\007 \001(\0162\017.dmi.Va"
+  "lueScale\"\300\001\n\nFormFactor\022\027\n\023FORM_FACTOR_U"
+  "NKNOWN\020\000\022\010\n\004QSFP\020\001\022\r\n\tQSFP_PLUS\020\002\022\n\n\006QSF"
+  "P28\020\003\022\007\n\003SFP\020\004\022\014\n\010SFP_PLUS\020\005\022\007\n\003XFP\020\006\022\010\n"
+  "\004CFP4\020\007\022\010\n\004CFP2\020\010\022\010\n\004CPAK\020\t\022\006\n\002X2\020\n\022\t\n\005O"
+  "THER\020\013\022\007\n\003CFP\020\014\022\014\n\010CFP2_ACO\020\r\022\014\n\010CFP2_DC"
+  "O\020\016\"h\n\004Type\022\020\n\014TYPE_UNKNOWN\020\000\022\014\n\010ETHERNE"
+  "T\020\001\022\010\n\004GPON\020\002\022\t\n\005XGPON\020\003\022\n\n\006XGSPON\020\004\022\010\n\004"
+  "CPON\020\005\022\013\n\007NG_PON2\020\006\022\010\n\004EPON\020\007\"\350\005\n\tCompon"
+  "ent\022\014\n\004name\030\001 \001(\t\022!\n\005class\030\002 \001(\0162\022.dmi.C"
+  "omponentType\022\023\n\013description\030\003 \001(\t\022\016\n\006par"
+  "ent\030\004 \001(\t\022\026\n\016parent_rel_pos\030\005 \001(\005\022 \n\010chi"
+  "ldren\030\006 \003(\0132\016.dmi.Component\022\024\n\014hardware_"
+  "rev\030\007 \001(\t\022\024\n\014firmware_rev\030\010 \001(\t\022\024\n\014softw"
+  "are_rev\030\t \001(\t\022\022\n\nserial_num\030\n \001(\t\022\020\n\010mfg"
+  "_name\030\013 \001(\t\022\022\n\nmodel_name\030\014 \001(\t\022\r\n\005alias"
+  "\030\r \001(\t\022\020\n\010asset_id\030\016 \001(\t\022\016\n\006is_fru\030\017 \001(\010"
+  "\022,\n\010mfg_date\030\020 \001(\0132\032.google.protobuf.Tim"
+  "estamp\022\025\n\003uri\030\021 \001(\0132\010.dmi.Uri\022\027\n\004uuid\030\022 "
+  "\001(\0132\t.dmi.Uuid\022\"\n\005state\030\023 \001(\0132\023.dmi.Comp"
+  "onentState\022-\n\013sensor_data\030\024 \003(\0132\030.dmi.Co"
+  "mponentSensorData\0221\n\tport_attr\0302 \001(\0132\034.d"
+  "mi.PortComponentAttributesH\000\022;\n\016containe"
+  "r_attr\0303 \001(\0132!.dmi.ContainerComponentAtt"
+  "ributesH\000\022/\n\010psu_attr\0304 \001(\0132\033.dmi.PsuCom"
+  "ponentAttributesH\000\022@\n\020transceiver_attr\0305"
+  " \001(\0132$.dmi.TransceiverComponentsAttribut"
+  "esH\000B\n\n\010specific\"\212\001\n\010Hardware\022/\n\013last_ch"
+  "ange\030\001 \001(\0132\032.google.protobuf.Timestamp\022\034"
+  "\n\004root\030\002 \001(\0132\016.dmi.Component\022/\n\013last_boo"
+  "ted\030\003 \001(\0132\032.google.protobuf.Timestamp\"\345\001"
+  "\n\023ModifiableComponent\022\014\n\004name\030\001 \001(\t\022!\n\005c"
+  "lass\030\002 \001(\0162\022.dmi.ComponentType\022\036\n\006parent"
+  "\030\003 \001(\0132\016.dmi.Component\022\026\n\016parent_rel_pos"
+  "\030\004 \001(\005\022\r\n\005alias\030\005 \001(\t\022\020\n\010asset_id\030\006 \001(\t\022"
+  "\025\n\003uri\030\007 \001(\0132\010.dmi.Uri\022-\n\013admin_state\030\010 "
+  "\001(\0162\030.dmi.ComponentAdminState*\264\003\n\rCompon"
+  "entType\022\034\n\030COMPONENT_TYPE_UNDEFINED\020\000\022\032\n"
+  "\026COMPONENT_TYPE_UNKNOWN\020\001\022\032\n\026COMPONENT_T"
+  "YPE_CHASSIS\020\002\022\034\n\030COMPONENT_TYPE_BACKPLAN"
+  "E\020\003\022\034\n\030COMPONENT_TYPE_CONTAINER\020\004\022\037\n\033COM"
+  "PONENT_TYPE_POWER_SUPPLY\020\005\022\026\n\022COMPONENT_"
+  "TYPE_FAN\020\006\022\031\n\025COMPONENT_TYPE_SENSOR\020\007\022\031\n"
+  "\025COMPONENT_TYPE_MODULE\020\010\022\027\n\023COMPONENT_TY"
+  "PE_PORT\020\t\022\026\n\022COMPONENT_TYPE_CPU\020\n\022\032\n\026COM"
+  "PONENT_TYPE_BATTERY\020\013\022\032\n\026COMPONENT_TYPE_"
+  "STORAGE\020\014\022\031\n\025COMPONENT_TYPE_MEMORY\020\r\022\036\n\032"
+  "COMPONENT_TYPE_TRANSCEIVER\020\016*\263\001\n\023Compone"
+  "ntAdminState\022\036\n\032COMP_ADMIN_STATE_UNDEFIN"
+  "ED\020\000\022\034\n\030COMP_ADMIN_STATE_UNKNOWN\020\001\022\033\n\027CO"
+  "MP_ADMIN_STATE_LOCKED\020\002\022\"\n\036COMP_ADMIN_ST"
+  "ATE_SHUTTING_DOWN\020\003\022\035\n\031COMP_ADMIN_STATE_"
+  "UNLOCKED\020\004*\250\001\n\022ComponentOperState\022\035\n\031COM"
+  "P_OPER_STATE_UNDEFINED\020\000\022\033\n\027COMP_OPER_ST"
+  "ATE_UNKNOWN\020\001\022\034\n\030COMP_OPER_STATE_DISABLE"
+  "D\020\002\022\033\n\027COMP_OPER_STATE_ENABLED\020\003\022\033\n\027COMP"
+  "_OPER_STATE_TESTING\020\004*\246\001\n\023ComponentUsage"
+  "State\022\036\n\032COMP_USAGE_STATE_UNDEFINED\020\000\022\034\n"
+  "\030COMP_USAGE_STATE_UNKNOWN\020\001\022\031\n\025COMP_USAG"
+  "E_STATE_IDLE\020\002\022\033\n\027COMP_USAGE_STATE_ACTIV"
+  "E\020\003\022\031\n\025COMP_USAGE_STATE_BUSY\020\004*\217\002\n\023Compo"
+  "nentAlarmState\022\036\n\032COMP_ALARM_STATE_UNDEF"
+  "INED\020\000\022\034\n\030COMP_ALARM_STATE_UNKNOWN\020\001\022!\n\035"
+  "COMP_ALARM_STATE_UNDER_REPAIR\020\002\022\035\n\031COMP_"
+  "ALARM_STATE_CRITICAL\020\003\022\032\n\026COMP_ALARM_STA"
+  "TE_MAJOR\020\004\022\032\n\026COMP_ALARM_STATE_MINOR\020\005\022\034"
+  "\n\030COMP_ALARM_STATE_WARNING\020\006\022\"\n\036COMP_ALA"
+  "RM_STATE_INDETERMINATE\020\007*\274\001\n\025ComponentSt"
+  "andbyState\022 \n\034COMP_STANDBY_STATE_UNDEFIN"
+  "ED\020\000\022\036\n\032COMP_STANDBY_STATE_UNKNOWN\020\001\022\032\n\026"
+  "COMP_STANDBY_STATE_HOT\020\002\022\033\n\027COMP_STANDBY"
+  "_STATE_COLD\020\003\022(\n$COMP_STANDBY_STATE_PROV"
+  "IDING_SERVICE\020\004*\211\003\n\rDataValueType\022\030\n\024VAL"
+  "UE_TYPE_UNDEFINED\020\000\022\024\n\020VALUE_TYPE_OTHER\020"
+  "\001\022\026\n\022VALUE_TYPE_UNKNOWN\020\002\022\027\n\023VALUE_TYPE_"
+  "VOLTS_AC\020\003\022\027\n\023VALUE_TYPE_VOLTS_DC\020\004\022\026\n\022V"
+  "ALUE_TYPE_AMPERES\020\005\022\024\n\020VALUE_TYPE_WATTS\020"
+  "\006\022\024\n\020VALUE_TYPE_HERTZ\020\007\022\026\n\022VALUE_TYPE_CE"
+  "LSIUS\020\010\022\031\n\025VALUE_TYPE_PERCENT_RH\020\t\022\022\n\016VA"
+  "LUE_TYPE_RPM\020\n\022\022\n\016VALUE_TYPE_CMM\020\013\022\032\n\026VA"
+  "LUE_TYPE_TRUTH_VALUE\020\014\022\026\n\022VALUE_TYPE_PER"
+  "CENT\020\r\022\025\n\021VALUE_TYPE_METERS\020\016\022\024\n\020VALUE_T"
+  "YPE_BYTES\020\017*\244\003\n\nValueScale\022\031\n\025VALUE_SCAL"
+  "E_UNDEFINED\020\000\022\025\n\021VALUE_SCALE_YOCTO\020\001\022\025\n\021"
+  "VALUE_SCALE_ZEPTO\020\002\022\024\n\020VALUE_SCALE_ATTO\020"
+  "\003\022\025\n\021VALUE_SCALE_FEMTO\020\004\022\024\n\020VALUE_SCALE_"
+  "PICO\020\005\022\024\n\020VALUE_SCALE_NANO\020\006\022\025\n\021VALUE_SC"
+  "ALE_MICRO\020\007\022\025\n\021VALUE_SCALE_MILLI\020\010\022\025\n\021VA"
+  "LUE_SCALE_UNITS\020\t\022\024\n\020VALUE_SCALE_KILO\020\n\022"
+  "\024\n\020VALUE_SCALE_MEGA\020\013\022\024\n\020VALUE_SCALE_GIG"
+  "A\020\014\022\024\n\020VALUE_SCALE_TERA\020\r\022\024\n\020VALUE_SCALE"
+  "_PETA\020\016\022\023\n\017VALUE_SCALE_EXA\020\017\022\025\n\021VALUE_SC"
+  "ALE_ZETTA\020\020\022\025\n\021VALUE_SCALE_YOTTA\020\021*\202\001\n\014S"
+  "ensorStatus\022\033\n\027SENSOR_STATUS_UNDEFINED\020\000"
+  "\022\024\n\020SENSOR_STATUS_OK\020\001\022\035\n\031SENSOR_STATUS_"
+  "UNAVAILABLE\020\002\022 \n\034SENSOR_STATUS_NONOPERAT"
+  "IONAL\020\003B;Z9github.com/opencord/device-ma"
+  "nagement-interface/v3/go/dmib\006proto3"
+  ;
+::google::protobuf::internal::DescriptorTable descriptor_table_dmi_2fhw_2eproto = {
+  false, InitDefaults_dmi_2fhw_2eproto, 
+  descriptor_table_protodef_dmi_2fhw_2eproto,
+  "dmi/hw.proto", &assign_descriptors_table_dmi_2fhw_2eproto, 5796,
+};
+
+void AddDescriptors_dmi_2fhw_2eproto() {
+  static constexpr ::google::protobuf::internal::InitFunc deps[1] =
+  {
+    ::AddDescriptors_google_2fprotobuf_2ftimestamp_2eproto,
+  };
+ ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fhw_2eproto, deps, 1);
+}
+
+// Force running AddDescriptors() at dynamic initialization time.
+static bool dynamic_init_dummy_dmi_2fhw_2eproto = []() { AddDescriptors_dmi_2fhw_2eproto(); return true; }();
+namespace dmi {
+const ::google::protobuf::EnumDescriptor* PortComponentAttributes_ConnectorType_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[0];
+}
+bool PortComponentAttributes_ConnectorType_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const PortComponentAttributes_ConnectorType PortComponentAttributes::CONNECTOR_TYPE_UNDEFINED;
+const PortComponentAttributes_ConnectorType PortComponentAttributes::RJ45;
+const PortComponentAttributes_ConnectorType PortComponentAttributes::FIBER_LC;
+const PortComponentAttributes_ConnectorType PortComponentAttributes::FIBER_SC_PC;
+const PortComponentAttributes_ConnectorType PortComponentAttributes::FIBER_MPO;
+const PortComponentAttributes_ConnectorType PortComponentAttributes::RS232;
+const PortComponentAttributes_ConnectorType PortComponentAttributes::ConnectorType_MIN;
+const PortComponentAttributes_ConnectorType PortComponentAttributes::ConnectorType_MAX;
+const int PortComponentAttributes::ConnectorType_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* PortComponentAttributes_Speed_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[1];
+}
+bool PortComponentAttributes_Speed_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const PortComponentAttributes_Speed PortComponentAttributes::SPEED_UNDEFINED;
+const PortComponentAttributes_Speed PortComponentAttributes::DYNAMIC;
+const PortComponentAttributes_Speed PortComponentAttributes::GIGABIT_1;
+const PortComponentAttributes_Speed PortComponentAttributes::GIGABIT_10;
+const PortComponentAttributes_Speed PortComponentAttributes::GIGABIT_25;
+const PortComponentAttributes_Speed PortComponentAttributes::GIGABIT_40;
+const PortComponentAttributes_Speed PortComponentAttributes::GIGABIT_100;
+const PortComponentAttributes_Speed PortComponentAttributes::GIGABIT_400;
+const PortComponentAttributes_Speed PortComponentAttributes::MEGABIT_2500;
+const PortComponentAttributes_Speed PortComponentAttributes::MEGABIT_1250;
+const PortComponentAttributes_Speed PortComponentAttributes::Speed_MIN;
+const PortComponentAttributes_Speed PortComponentAttributes::Speed_MAX;
+const int PortComponentAttributes::Speed_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* PortComponentAttributes_Protocol_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[2];
+}
+bool PortComponentAttributes_Protocol_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const PortComponentAttributes_Protocol PortComponentAttributes::PROTOCOL_UNDEFINED;
+const PortComponentAttributes_Protocol PortComponentAttributes::ETHERNET;
+const PortComponentAttributes_Protocol PortComponentAttributes::GPON;
+const PortComponentAttributes_Protocol PortComponentAttributes::XGPON;
+const PortComponentAttributes_Protocol PortComponentAttributes::XGSPON;
+const PortComponentAttributes_Protocol PortComponentAttributes::GFAST;
+const PortComponentAttributes_Protocol PortComponentAttributes::SERIAL;
+const PortComponentAttributes_Protocol PortComponentAttributes::EPON;
+const PortComponentAttributes_Protocol PortComponentAttributes::BITS;
+const PortComponentAttributes_Protocol PortComponentAttributes::Protocol_MIN;
+const PortComponentAttributes_Protocol PortComponentAttributes::Protocol_MAX;
+const int PortComponentAttributes::Protocol_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* PsuComponentAttributes_SupportedVoltage_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[3];
+}
+bool PsuComponentAttributes_SupportedVoltage_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const PsuComponentAttributes_SupportedVoltage PsuComponentAttributes::SUPPORTED_VOLTAGE_UNDEFINED;
+const PsuComponentAttributes_SupportedVoltage PsuComponentAttributes::V48;
+const PsuComponentAttributes_SupportedVoltage PsuComponentAttributes::V230;
+const PsuComponentAttributes_SupportedVoltage PsuComponentAttributes::V115;
+const PsuComponentAttributes_SupportedVoltage PsuComponentAttributes::SupportedVoltage_MIN;
+const PsuComponentAttributes_SupportedVoltage PsuComponentAttributes::SupportedVoltage_MAX;
+const int PsuComponentAttributes::SupportedVoltage_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* TransceiverComponentsAttributes_FormFactor_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[4];
+}
+bool TransceiverComponentsAttributes_FormFactor_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::FORM_FACTOR_UNKNOWN;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::QSFP;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::QSFP_PLUS;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::QSFP28;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::SFP;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::SFP_PLUS;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::XFP;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::CFP4;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::CFP2;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::CPAK;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::X2;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::OTHER;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::CFP;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::CFP2_ACO;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::CFP2_DCO;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::FormFactor_MIN;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::FormFactor_MAX;
+const int TransceiverComponentsAttributes::FormFactor_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* TransceiverComponentsAttributes_Type_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[5];
+}
+bool TransceiverComponentsAttributes_Type_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const TransceiverComponentsAttributes_Type TransceiverComponentsAttributes::TYPE_UNKNOWN;
+const TransceiverComponentsAttributes_Type TransceiverComponentsAttributes::ETHERNET;
+const TransceiverComponentsAttributes_Type TransceiverComponentsAttributes::GPON;
+const TransceiverComponentsAttributes_Type TransceiverComponentsAttributes::XGPON;
+const TransceiverComponentsAttributes_Type TransceiverComponentsAttributes::XGSPON;
+const TransceiverComponentsAttributes_Type TransceiverComponentsAttributes::CPON;
+const TransceiverComponentsAttributes_Type TransceiverComponentsAttributes::NG_PON2;
+const TransceiverComponentsAttributes_Type TransceiverComponentsAttributes::EPON;
+const TransceiverComponentsAttributes_Type TransceiverComponentsAttributes::Type_MIN;
+const TransceiverComponentsAttributes_Type TransceiverComponentsAttributes::Type_MAX;
+const int TransceiverComponentsAttributes::Type_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* ComponentType_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[6];
+}
+bool ComponentType_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+      return true;
+    default:
+      return false;
+  }
+}
+
+const ::google::protobuf::EnumDescriptor* ComponentAdminState_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[7];
+}
+bool ComponentAdminState_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+const ::google::protobuf::EnumDescriptor* ComponentOperState_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[8];
+}
+bool ComponentOperState_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+const ::google::protobuf::EnumDescriptor* ComponentUsageState_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[9];
+}
+bool ComponentUsageState_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+const ::google::protobuf::EnumDescriptor* ComponentAlarmState_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[10];
+}
+bool ComponentAlarmState_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+      return true;
+    default:
+      return false;
+  }
+}
+
+const ::google::protobuf::EnumDescriptor* ComponentStandbyState_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[11];
+}
+bool ComponentStandbyState_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+const ::google::protobuf::EnumDescriptor* DataValueType_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[12];
+}
+bool DataValueType_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+      return true;
+    default:
+      return false;
+  }
+}
+
+const ::google::protobuf::EnumDescriptor* ValueScale_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[13];
+}
+bool ValueScale_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+      return true;
+    default:
+      return false;
+  }
+}
+
+const ::google::protobuf::EnumDescriptor* SensorStatus_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_2eproto[14];
+}
+bool SensorStatus_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+
+// ===================================================================
+
+void Uuid::InitAsDefaultInstance() {
+}
+class Uuid::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Uuid::kUuidFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Uuid::Uuid()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.Uuid)
+}
+Uuid::Uuid(const Uuid& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  uuid_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.uuid().size() > 0) {
+    uuid_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.uuid_);
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.Uuid)
+}
+
+void Uuid::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_Uuid_dmi_2fhw_2eproto.base);
+  uuid_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+Uuid::~Uuid() {
+  // @@protoc_insertion_point(destructor:dmi.Uuid)
+  SharedDtor();
+}
+
+void Uuid::SharedDtor() {
+  uuid_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void Uuid::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const Uuid& Uuid::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_Uuid_dmi_2fhw_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void Uuid::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.Uuid)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  uuid_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* Uuid::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<Uuid*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // string uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Uuid.uuid");
+        object = msg->mutable_uuid();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool Uuid::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.Uuid)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // string uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_uuid()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->uuid().data(), static_cast<int>(this->uuid().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Uuid.uuid"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.Uuid)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.Uuid)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void Uuid::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.Uuid)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string uuid = 1;
+  if (this->uuid().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->uuid().data(), static_cast<int>(this->uuid().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Uuid.uuid");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->uuid(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.Uuid)
+}
+
+::google::protobuf::uint8* Uuid::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.Uuid)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string uuid = 1;
+  if (this->uuid().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->uuid().data(), static_cast<int>(this->uuid().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Uuid.uuid");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->uuid(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.Uuid)
+  return target;
+}
+
+size_t Uuid::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.Uuid)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string uuid = 1;
+  if (this->uuid().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->uuid());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void Uuid::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.Uuid)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Uuid* source =
+      ::google::protobuf::DynamicCastToGenerated<Uuid>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.Uuid)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.Uuid)
+    MergeFrom(*source);
+  }
+}
+
+void Uuid::MergeFrom(const Uuid& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.Uuid)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.uuid().size() > 0) {
+
+    uuid_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.uuid_);
+  }
+}
+
+void Uuid::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.Uuid)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Uuid::CopyFrom(const Uuid& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.Uuid)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Uuid::IsInitialized() const {
+  return true;
+}
+
+void Uuid::Swap(Uuid* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Uuid::InternalSwap(Uuid* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  uuid_.Swap(&other->uuid_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+}
+
+::google::protobuf::Metadata Uuid::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_2eproto);
+  return ::file_level_metadata_dmi_2fhw_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void HardwareID::InitAsDefaultInstance() {
+  ::dmi::_HardwareID_default_instance_._instance.get_mutable()->uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class HardwareID::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& uuid(const HardwareID* msg);
+};
+
+const ::dmi::Uuid&
+HardwareID::HasBitSetters::uuid(const HardwareID* msg) {
+  return *msg->uuid_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int HardwareID::kUuidFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+HardwareID::HardwareID()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.HardwareID)
+}
+HardwareID::HardwareID(const HardwareID& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_uuid()) {
+    uuid_ = new ::dmi::Uuid(*from.uuid_);
+  } else {
+    uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.HardwareID)
+}
+
+void HardwareID::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_HardwareID_dmi_2fhw_2eproto.base);
+  uuid_ = nullptr;
+}
+
+HardwareID::~HardwareID() {
+  // @@protoc_insertion_point(destructor:dmi.HardwareID)
+  SharedDtor();
+}
+
+void HardwareID::SharedDtor() {
+  if (this != internal_default_instance()) delete uuid_;
+}
+
+void HardwareID::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const HardwareID& HardwareID::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_HardwareID_dmi_2fhw_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void HardwareID::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.HardwareID)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && uuid_ != nullptr) {
+    delete uuid_;
+  }
+  uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* HardwareID::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<HardwareID*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool HardwareID::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.HardwareID)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.HardwareID)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.HardwareID)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void HardwareID::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.HardwareID)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid uuid = 1;
+  if (this->has_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::uuid(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.HardwareID)
+}
+
+::google::protobuf::uint8* HardwareID::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.HardwareID)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid uuid = 1;
+  if (this->has_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::uuid(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.HardwareID)
+  return target;
+}
+
+size_t HardwareID::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.HardwareID)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.Uuid uuid = 1;
+  if (this->has_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void HardwareID::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.HardwareID)
+  GOOGLE_DCHECK_NE(&from, this);
+  const HardwareID* source =
+      ::google::protobuf::DynamicCastToGenerated<HardwareID>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.HardwareID)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.HardwareID)
+    MergeFrom(*source);
+  }
+}
+
+void HardwareID::MergeFrom(const HardwareID& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.HardwareID)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_uuid()) {
+    mutable_uuid()->::dmi::Uuid::MergeFrom(from.uuid());
+  }
+}
+
+void HardwareID::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.HardwareID)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void HardwareID::CopyFrom(const HardwareID& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.HardwareID)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool HardwareID::IsInitialized() const {
+  return true;
+}
+
+void HardwareID::Swap(HardwareID* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void HardwareID::InternalSwap(HardwareID* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(uuid_, other->uuid_);
+}
+
+::google::protobuf::Metadata HardwareID::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_2eproto);
+  return ::file_level_metadata_dmi_2fhw_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void Uri::InitAsDefaultInstance() {
+}
+class Uri::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Uri::kUriFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Uri::Uri()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.Uri)
+}
+Uri::Uri(const Uri& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  uri_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.uri().size() > 0) {
+    uri_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.uri_);
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.Uri)
+}
+
+void Uri::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_Uri_dmi_2fhw_2eproto.base);
+  uri_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+Uri::~Uri() {
+  // @@protoc_insertion_point(destructor:dmi.Uri)
+  SharedDtor();
+}
+
+void Uri::SharedDtor() {
+  uri_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void Uri::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const Uri& Uri::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_Uri_dmi_2fhw_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void Uri::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.Uri)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  uri_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* Uri::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<Uri*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // string uri = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Uri.uri");
+        object = msg->mutable_uri();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool Uri::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.Uri)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // string uri = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_uri()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->uri().data(), static_cast<int>(this->uri().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Uri.uri"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.Uri)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.Uri)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void Uri::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.Uri)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string uri = 1;
+  if (this->uri().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->uri().data(), static_cast<int>(this->uri().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Uri.uri");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->uri(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.Uri)
+}
+
+::google::protobuf::uint8* Uri::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.Uri)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string uri = 1;
+  if (this->uri().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->uri().data(), static_cast<int>(this->uri().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Uri.uri");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->uri(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.Uri)
+  return target;
+}
+
+size_t Uri::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.Uri)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string uri = 1;
+  if (this->uri().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->uri());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void Uri::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.Uri)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Uri* source =
+      ::google::protobuf::DynamicCastToGenerated<Uri>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.Uri)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.Uri)
+    MergeFrom(*source);
+  }
+}
+
+void Uri::MergeFrom(const Uri& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.Uri)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.uri().size() > 0) {
+
+    uri_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.uri_);
+  }
+}
+
+void Uri::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.Uri)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Uri::CopyFrom(const Uri& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.Uri)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Uri::IsInitialized() const {
+  return true;
+}
+
+void Uri::Swap(Uri* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Uri::InternalSwap(Uri* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  uri_.Swap(&other->uri_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+}
+
+::google::protobuf::Metadata Uri::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_2eproto);
+  return ::file_level_metadata_dmi_2fhw_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ComponentState::InitAsDefaultInstance() {
+  ::dmi::_ComponentState_default_instance_._instance.get_mutable()->state_last_changed_ = const_cast< ::google::protobuf::Timestamp*>(
+      ::google::protobuf::Timestamp::internal_default_instance());
+}
+class ComponentState::HasBitSetters {
+ public:
+  static const ::google::protobuf::Timestamp& state_last_changed(const ComponentState* msg);
+};
+
+const ::google::protobuf::Timestamp&
+ComponentState::HasBitSetters::state_last_changed(const ComponentState* msg) {
+  return *msg->state_last_changed_;
+}
+void ComponentState::clear_state_last_changed() {
+  if (GetArenaNoVirtual() == nullptr && state_last_changed_ != nullptr) {
+    delete state_last_changed_;
+  }
+  state_last_changed_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ComponentState::kStateLastChangedFieldNumber;
+const int ComponentState::kAdminStateFieldNumber;
+const int ComponentState::kOperStateFieldNumber;
+const int ComponentState::kUsageStateFieldNumber;
+const int ComponentState::kAlarmStateFieldNumber;
+const int ComponentState::kStandbyStateFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ComponentState::ComponentState()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ComponentState)
+}
+ComponentState::ComponentState(const ComponentState& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_state_last_changed()) {
+    state_last_changed_ = new ::google::protobuf::Timestamp(*from.state_last_changed_);
+  } else {
+    state_last_changed_ = nullptr;
+  }
+  ::memcpy(&admin_state_, &from.admin_state_,
+    static_cast<size_t>(reinterpret_cast<char*>(&standby_state_) -
+    reinterpret_cast<char*>(&admin_state_)) + sizeof(standby_state_));
+  // @@protoc_insertion_point(copy_constructor:dmi.ComponentState)
+}
+
+void ComponentState::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ComponentState_dmi_2fhw_2eproto.base);
+  ::memset(&state_last_changed_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&standby_state_) -
+      reinterpret_cast<char*>(&state_last_changed_)) + sizeof(standby_state_));
+}
+
+ComponentState::~ComponentState() {
+  // @@protoc_insertion_point(destructor:dmi.ComponentState)
+  SharedDtor();
+}
+
+void ComponentState::SharedDtor() {
+  if (this != internal_default_instance()) delete state_last_changed_;
+}
+
+void ComponentState::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ComponentState& ComponentState::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ComponentState_dmi_2fhw_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ComponentState::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ComponentState)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && state_last_changed_ != nullptr) {
+    delete state_last_changed_;
+  }
+  state_last_changed_ = nullptr;
+  ::memset(&admin_state_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&standby_state_) -
+      reinterpret_cast<char*>(&admin_state_)) + sizeof(standby_state_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ComponentState::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ComponentState*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .google.protobuf.Timestamp state_last_changed = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::google::protobuf::Timestamp::_InternalParse;
+        object = msg->mutable_state_last_changed();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.ComponentAdminState admin_state = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_admin_state(static_cast<::dmi::ComponentAdminState>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ComponentOperState oper_state = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_oper_state(static_cast<::dmi::ComponentOperState>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ComponentUsageState usage_state = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 32) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_usage_state(static_cast<::dmi::ComponentUsageState>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ComponentAlarmState alarm_state = 5;
+      case 5: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 40) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_alarm_state(static_cast<::dmi::ComponentAlarmState>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ComponentStandbyState standby_state = 6;
+      case 6: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 48) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_standby_state(static_cast<::dmi::ComponentStandbyState>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ComponentState::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ComponentState)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .google.protobuf.Timestamp state_last_changed = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_state_last_changed()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ComponentAdminState admin_state = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_admin_state(static_cast< ::dmi::ComponentAdminState >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ComponentOperState oper_state = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_oper_state(static_cast< ::dmi::ComponentOperState >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ComponentUsageState usage_state = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (32 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_usage_state(static_cast< ::dmi::ComponentUsageState >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ComponentAlarmState alarm_state = 5;
+      case 5: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (40 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_alarm_state(static_cast< ::dmi::ComponentAlarmState >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ComponentStandbyState standby_state = 6;
+      case 6: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (48 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_standby_state(static_cast< ::dmi::ComponentStandbyState >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ComponentState)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ComponentState)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ComponentState::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ComponentState)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .google.protobuf.Timestamp state_last_changed = 1;
+  if (this->has_state_last_changed()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::state_last_changed(this), output);
+  }
+
+  // .dmi.ComponentAdminState admin_state = 2;
+  if (this->admin_state() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->admin_state(), output);
+  }
+
+  // .dmi.ComponentOperState oper_state = 3;
+  if (this->oper_state() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      3, this->oper_state(), output);
+  }
+
+  // .dmi.ComponentUsageState usage_state = 4;
+  if (this->usage_state() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      4, this->usage_state(), output);
+  }
+
+  // .dmi.ComponentAlarmState alarm_state = 5;
+  if (this->alarm_state() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      5, this->alarm_state(), output);
+  }
+
+  // .dmi.ComponentStandbyState standby_state = 6;
+  if (this->standby_state() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      6, this->standby_state(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ComponentState)
+}
+
+::google::protobuf::uint8* ComponentState::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ComponentState)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .google.protobuf.Timestamp state_last_changed = 1;
+  if (this->has_state_last_changed()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::state_last_changed(this), target);
+  }
+
+  // .dmi.ComponentAdminState admin_state = 2;
+  if (this->admin_state() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->admin_state(), target);
+  }
+
+  // .dmi.ComponentOperState oper_state = 3;
+  if (this->oper_state() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      3, this->oper_state(), target);
+  }
+
+  // .dmi.ComponentUsageState usage_state = 4;
+  if (this->usage_state() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      4, this->usage_state(), target);
+  }
+
+  // .dmi.ComponentAlarmState alarm_state = 5;
+  if (this->alarm_state() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      5, this->alarm_state(), target);
+  }
+
+  // .dmi.ComponentStandbyState standby_state = 6;
+  if (this->standby_state() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      6, this->standby_state(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ComponentState)
+  return target;
+}
+
+size_t ComponentState::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ComponentState)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .google.protobuf.Timestamp state_last_changed = 1;
+  if (this->has_state_last_changed()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *state_last_changed_);
+  }
+
+  // .dmi.ComponentAdminState admin_state = 2;
+  if (this->admin_state() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->admin_state());
+  }
+
+  // .dmi.ComponentOperState oper_state = 3;
+  if (this->oper_state() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->oper_state());
+  }
+
+  // .dmi.ComponentUsageState usage_state = 4;
+  if (this->usage_state() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->usage_state());
+  }
+
+  // .dmi.ComponentAlarmState alarm_state = 5;
+  if (this->alarm_state() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->alarm_state());
+  }
+
+  // .dmi.ComponentStandbyState standby_state = 6;
+  if (this->standby_state() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->standby_state());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ComponentState::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ComponentState)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ComponentState* source =
+      ::google::protobuf::DynamicCastToGenerated<ComponentState>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ComponentState)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ComponentState)
+    MergeFrom(*source);
+  }
+}
+
+void ComponentState::MergeFrom(const ComponentState& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ComponentState)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_state_last_changed()) {
+    mutable_state_last_changed()->::google::protobuf::Timestamp::MergeFrom(from.state_last_changed());
+  }
+  if (from.admin_state() != 0) {
+    set_admin_state(from.admin_state());
+  }
+  if (from.oper_state() != 0) {
+    set_oper_state(from.oper_state());
+  }
+  if (from.usage_state() != 0) {
+    set_usage_state(from.usage_state());
+  }
+  if (from.alarm_state() != 0) {
+    set_alarm_state(from.alarm_state());
+  }
+  if (from.standby_state() != 0) {
+    set_standby_state(from.standby_state());
+  }
+}
+
+void ComponentState::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ComponentState)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ComponentState::CopyFrom(const ComponentState& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ComponentState)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ComponentState::IsInitialized() const {
+  return true;
+}
+
+void ComponentState::Swap(ComponentState* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ComponentState::InternalSwap(ComponentState* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(state_last_changed_, other->state_last_changed_);
+  swap(admin_state_, other->admin_state_);
+  swap(oper_state_, other->oper_state_);
+  swap(usage_state_, other->usage_state_);
+  swap(alarm_state_, other->alarm_state_);
+  swap(standby_state_, other->standby_state_);
+}
+
+::google::protobuf::Metadata ComponentState::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_2eproto);
+  return ::file_level_metadata_dmi_2fhw_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ComponentSensorData::InitAsDefaultInstance() {
+  ::dmi::_ComponentSensorData_default_instance_._instance.get_mutable()->timestamp_ = const_cast< ::google::protobuf::Timestamp*>(
+      ::google::protobuf::Timestamp::internal_default_instance());
+}
+class ComponentSensorData::HasBitSetters {
+ public:
+  static const ::google::protobuf::Timestamp& timestamp(const ComponentSensorData* msg);
+};
+
+const ::google::protobuf::Timestamp&
+ComponentSensorData::HasBitSetters::timestamp(const ComponentSensorData* msg) {
+  return *msg->timestamp_;
+}
+void ComponentSensorData::clear_timestamp() {
+  if (GetArenaNoVirtual() == nullptr && timestamp_ != nullptr) {
+    delete timestamp_;
+  }
+  timestamp_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ComponentSensorData::kValueFieldNumber;
+const int ComponentSensorData::kTypeFieldNumber;
+const int ComponentSensorData::kScaleFieldNumber;
+const int ComponentSensorData::kPrecisionFieldNumber;
+const int ComponentSensorData::kStatusFieldNumber;
+const int ComponentSensorData::kUnitsDisplayFieldNumber;
+const int ComponentSensorData::kTimestampFieldNumber;
+const int ComponentSensorData::kValueUpdateRateFieldNumber;
+const int ComponentSensorData::kDataTypeFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ComponentSensorData::ComponentSensorData()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ComponentSensorData)
+}
+ComponentSensorData::ComponentSensorData(const ComponentSensorData& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  units_display_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.units_display().size() > 0) {
+    units_display_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.units_display_);
+  }
+  data_type_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.data_type().size() > 0) {
+    data_type_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.data_type_);
+  }
+  if (from.has_timestamp()) {
+    timestamp_ = new ::google::protobuf::Timestamp(*from.timestamp_);
+  } else {
+    timestamp_ = nullptr;
+  }
+  ::memcpy(&value_, &from.value_,
+    static_cast<size_t>(reinterpret_cast<char*>(&value_update_rate_) -
+    reinterpret_cast<char*>(&value_)) + sizeof(value_update_rate_));
+  // @@protoc_insertion_point(copy_constructor:dmi.ComponentSensorData)
+}
+
+void ComponentSensorData::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ComponentSensorData_dmi_2fhw_2eproto.base);
+  units_display_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  data_type_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&timestamp_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&value_update_rate_) -
+      reinterpret_cast<char*>(&timestamp_)) + sizeof(value_update_rate_));
+}
+
+ComponentSensorData::~ComponentSensorData() {
+  // @@protoc_insertion_point(destructor:dmi.ComponentSensorData)
+  SharedDtor();
+}
+
+void ComponentSensorData::SharedDtor() {
+  units_display_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  data_type_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete timestamp_;
+}
+
+void ComponentSensorData::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ComponentSensorData& ComponentSensorData::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ComponentSensorData_dmi_2fhw_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ComponentSensorData::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ComponentSensorData)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  units_display_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  data_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && timestamp_ != nullptr) {
+    delete timestamp_;
+  }
+  timestamp_ = nullptr;
+  ::memset(&value_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&value_update_rate_) -
+      reinterpret_cast<char*>(&value_)) + sizeof(value_update_rate_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ComponentSensorData::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ComponentSensorData*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // int32 value = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        msg->set_value(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.DataValueType type = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_type(static_cast<::dmi::DataValueType>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ValueScale scale = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_scale(static_cast<::dmi::ValueScale>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // int32 precision = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 32) goto handle_unusual;
+        msg->set_precision(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.SensorStatus status = 5;
+      case 5: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 40) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::SensorStatus>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string units_display = 6;
+      case 6: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 50) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ComponentSensorData.units_display");
+        object = msg->mutable_units_display();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // .google.protobuf.Timestamp timestamp = 7;
+      case 7: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::google::protobuf::Timestamp::_InternalParse;
+        object = msg->mutable_timestamp();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // uint32 value_update_rate = 8;
+      case 8: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 64) goto handle_unusual;
+        msg->set_value_update_rate(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string data_type = 9;
+      case 9: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 74) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ComponentSensorData.data_type");
+        object = msg->mutable_data_type();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ComponentSensorData::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ComponentSensorData)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // int32 value = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &value_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.DataValueType type = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_type(static_cast< ::dmi::DataValueType >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ValueScale scale = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_scale(static_cast< ::dmi::ValueScale >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // int32 precision = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (32 & 0xFF)) {
+
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &precision_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.SensorStatus status = 5;
+      case 5: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (40 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::SensorStatus >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string units_display = 6;
+      case 6: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (50 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_units_display()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->units_display().data(), static_cast<int>(this->units_display().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ComponentSensorData.units_display"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .google.protobuf.Timestamp timestamp = 7;
+      case 7: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (58 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_timestamp()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // uint32 value_update_rate = 8;
+      case 8: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (64 & 0xFF)) {
+
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &value_update_rate_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string data_type = 9;
+      case 9: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (74 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_data_type()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->data_type().data(), static_cast<int>(this->data_type().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ComponentSensorData.data_type"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ComponentSensorData)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ComponentSensorData)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ComponentSensorData::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ComponentSensorData)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // int32 value = 1;
+  if (this->value() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->value(), output);
+  }
+
+  // .dmi.DataValueType type = 2;
+  if (this->type() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->type(), output);
+  }
+
+  // .dmi.ValueScale scale = 3;
+  if (this->scale() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      3, this->scale(), output);
+  }
+
+  // int32 precision = 4;
+  if (this->precision() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(4, this->precision(), output);
+  }
+
+  // .dmi.SensorStatus status = 5;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      5, this->status(), output);
+  }
+
+  // string units_display = 6;
+  if (this->units_display().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->units_display().data(), static_cast<int>(this->units_display().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ComponentSensorData.units_display");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      6, this->units_display(), output);
+  }
+
+  // .google.protobuf.Timestamp timestamp = 7;
+  if (this->has_timestamp()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      7, HasBitSetters::timestamp(this), output);
+  }
+
+  // uint32 value_update_rate = 8;
+  if (this->value_update_rate() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(8, this->value_update_rate(), output);
+  }
+
+  // string data_type = 9;
+  if (this->data_type().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->data_type().data(), static_cast<int>(this->data_type().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ComponentSensorData.data_type");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      9, this->data_type(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ComponentSensorData)
+}
+
+::google::protobuf::uint8* ComponentSensorData::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ComponentSensorData)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // int32 value = 1;
+  if (this->value() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->value(), target);
+  }
+
+  // .dmi.DataValueType type = 2;
+  if (this->type() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->type(), target);
+  }
+
+  // .dmi.ValueScale scale = 3;
+  if (this->scale() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      3, this->scale(), target);
+  }
+
+  // int32 precision = 4;
+  if (this->precision() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(4, this->precision(), target);
+  }
+
+  // .dmi.SensorStatus status = 5;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      5, this->status(), target);
+  }
+
+  // string units_display = 6;
+  if (this->units_display().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->units_display().data(), static_cast<int>(this->units_display().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ComponentSensorData.units_display");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        6, this->units_display(), target);
+  }
+
+  // .google.protobuf.Timestamp timestamp = 7;
+  if (this->has_timestamp()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        7, HasBitSetters::timestamp(this), target);
+  }
+
+  // uint32 value_update_rate = 8;
+  if (this->value_update_rate() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(8, this->value_update_rate(), target);
+  }
+
+  // string data_type = 9;
+  if (this->data_type().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->data_type().data(), static_cast<int>(this->data_type().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ComponentSensorData.data_type");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        9, this->data_type(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ComponentSensorData)
+  return target;
+}
+
+size_t ComponentSensorData::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ComponentSensorData)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string units_display = 6;
+  if (this->units_display().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->units_display());
+  }
+
+  // string data_type = 9;
+  if (this->data_type().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->data_type());
+  }
+
+  // .google.protobuf.Timestamp timestamp = 7;
+  if (this->has_timestamp()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *timestamp_);
+  }
+
+  // int32 value = 1;
+  if (this->value() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int32Size(
+        this->value());
+  }
+
+  // .dmi.DataValueType type = 2;
+  if (this->type() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->type());
+  }
+
+  // .dmi.ValueScale scale = 3;
+  if (this->scale() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->scale());
+  }
+
+  // int32 precision = 4;
+  if (this->precision() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int32Size(
+        this->precision());
+  }
+
+  // .dmi.SensorStatus status = 5;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // uint32 value_update_rate = 8;
+  if (this->value_update_rate() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::UInt32Size(
+        this->value_update_rate());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ComponentSensorData::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ComponentSensorData)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ComponentSensorData* source =
+      ::google::protobuf::DynamicCastToGenerated<ComponentSensorData>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ComponentSensorData)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ComponentSensorData)
+    MergeFrom(*source);
+  }
+}
+
+void ComponentSensorData::MergeFrom(const ComponentSensorData& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ComponentSensorData)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.units_display().size() > 0) {
+
+    units_display_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.units_display_);
+  }
+  if (from.data_type().size() > 0) {
+
+    data_type_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.data_type_);
+  }
+  if (from.has_timestamp()) {
+    mutable_timestamp()->::google::protobuf::Timestamp::MergeFrom(from.timestamp());
+  }
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+  if (from.type() != 0) {
+    set_type(from.type());
+  }
+  if (from.scale() != 0) {
+    set_scale(from.scale());
+  }
+  if (from.precision() != 0) {
+    set_precision(from.precision());
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.value_update_rate() != 0) {
+    set_value_update_rate(from.value_update_rate());
+  }
+}
+
+void ComponentSensorData::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ComponentSensorData)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ComponentSensorData::CopyFrom(const ComponentSensorData& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ComponentSensorData)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ComponentSensorData::IsInitialized() const {
+  return true;
+}
+
+void ComponentSensorData::Swap(ComponentSensorData* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ComponentSensorData::InternalSwap(ComponentSensorData* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  units_display_.Swap(&other->units_display_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  data_type_.Swap(&other->data_type_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(timestamp_, other->timestamp_);
+  swap(value_, other->value_);
+  swap(type_, other->type_);
+  swap(scale_, other->scale_);
+  swap(precision_, other->precision_);
+  swap(status_, other->status_);
+  swap(value_update_rate_, other->value_update_rate_);
+}
+
+::google::protobuf::Metadata ComponentSensorData::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_2eproto);
+  return ::file_level_metadata_dmi_2fhw_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void PortComponentAttributes::InitAsDefaultInstance() {
+}
+class PortComponentAttributes::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int PortComponentAttributes::kConnectorTypeFieldNumber;
+const int PortComponentAttributes::kSpeedFieldNumber;
+const int PortComponentAttributes::kProtocolFieldNumber;
+const int PortComponentAttributes::kPhysicalLabelFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+PortComponentAttributes::PortComponentAttributes()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.PortComponentAttributes)
+}
+PortComponentAttributes::PortComponentAttributes(const PortComponentAttributes& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  physical_label_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.physical_label().size() > 0) {
+    physical_label_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.physical_label_);
+  }
+  ::memcpy(&connector_type_, &from.connector_type_,
+    static_cast<size_t>(reinterpret_cast<char*>(&protocol_) -
+    reinterpret_cast<char*>(&connector_type_)) + sizeof(protocol_));
+  // @@protoc_insertion_point(copy_constructor:dmi.PortComponentAttributes)
+}
+
+void PortComponentAttributes::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_PortComponentAttributes_dmi_2fhw_2eproto.base);
+  physical_label_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&connector_type_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&protocol_) -
+      reinterpret_cast<char*>(&connector_type_)) + sizeof(protocol_));
+}
+
+PortComponentAttributes::~PortComponentAttributes() {
+  // @@protoc_insertion_point(destructor:dmi.PortComponentAttributes)
+  SharedDtor();
+}
+
+void PortComponentAttributes::SharedDtor() {
+  physical_label_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void PortComponentAttributes::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const PortComponentAttributes& PortComponentAttributes::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_PortComponentAttributes_dmi_2fhw_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void PortComponentAttributes::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.PortComponentAttributes)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  physical_label_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&connector_type_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&protocol_) -
+      reinterpret_cast<char*>(&connector_type_)) + sizeof(protocol_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* PortComponentAttributes::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<PortComponentAttributes*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.PortComponentAttributes.ConnectorType connector_type = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_connector_type(static_cast<::dmi::PortComponentAttributes_ConnectorType>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.PortComponentAttributes.Speed speed = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_speed(static_cast<::dmi::PortComponentAttributes_Speed>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.PortComponentAttributes.Protocol protocol = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_protocol(static_cast<::dmi::PortComponentAttributes_Protocol>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string physical_label = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.PortComponentAttributes.physical_label");
+        object = msg->mutable_physical_label();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool PortComponentAttributes::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.PortComponentAttributes)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.PortComponentAttributes.ConnectorType connector_type = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_connector_type(static_cast< ::dmi::PortComponentAttributes_ConnectorType >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.PortComponentAttributes.Speed speed = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_speed(static_cast< ::dmi::PortComponentAttributes_Speed >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.PortComponentAttributes.Protocol protocol = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_protocol(static_cast< ::dmi::PortComponentAttributes_Protocol >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string physical_label = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_physical_label()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->physical_label().data(), static_cast<int>(this->physical_label().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.PortComponentAttributes.physical_label"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.PortComponentAttributes)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.PortComponentAttributes)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void PortComponentAttributes::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.PortComponentAttributes)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.PortComponentAttributes.ConnectorType connector_type = 1;
+  if (this->connector_type() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->connector_type(), output);
+  }
+
+  // .dmi.PortComponentAttributes.Speed speed = 2;
+  if (this->speed() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->speed(), output);
+  }
+
+  // .dmi.PortComponentAttributes.Protocol protocol = 3;
+  if (this->protocol() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      3, this->protocol(), output);
+  }
+
+  // string physical_label = 4;
+  if (this->physical_label().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->physical_label().data(), static_cast<int>(this->physical_label().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.PortComponentAttributes.physical_label");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->physical_label(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.PortComponentAttributes)
+}
+
+::google::protobuf::uint8* PortComponentAttributes::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.PortComponentAttributes)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.PortComponentAttributes.ConnectorType connector_type = 1;
+  if (this->connector_type() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->connector_type(), target);
+  }
+
+  // .dmi.PortComponentAttributes.Speed speed = 2;
+  if (this->speed() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->speed(), target);
+  }
+
+  // .dmi.PortComponentAttributes.Protocol protocol = 3;
+  if (this->protocol() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      3, this->protocol(), target);
+  }
+
+  // string physical_label = 4;
+  if (this->physical_label().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->physical_label().data(), static_cast<int>(this->physical_label().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.PortComponentAttributes.physical_label");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->physical_label(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.PortComponentAttributes)
+  return target;
+}
+
+size_t PortComponentAttributes::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.PortComponentAttributes)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string physical_label = 4;
+  if (this->physical_label().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->physical_label());
+  }
+
+  // .dmi.PortComponentAttributes.ConnectorType connector_type = 1;
+  if (this->connector_type() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->connector_type());
+  }
+
+  // .dmi.PortComponentAttributes.Speed speed = 2;
+  if (this->speed() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->speed());
+  }
+
+  // .dmi.PortComponentAttributes.Protocol protocol = 3;
+  if (this->protocol() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->protocol());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void PortComponentAttributes::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.PortComponentAttributes)
+  GOOGLE_DCHECK_NE(&from, this);
+  const PortComponentAttributes* source =
+      ::google::protobuf::DynamicCastToGenerated<PortComponentAttributes>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.PortComponentAttributes)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.PortComponentAttributes)
+    MergeFrom(*source);
+  }
+}
+
+void PortComponentAttributes::MergeFrom(const PortComponentAttributes& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.PortComponentAttributes)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.physical_label().size() > 0) {
+
+    physical_label_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.physical_label_);
+  }
+  if (from.connector_type() != 0) {
+    set_connector_type(from.connector_type());
+  }
+  if (from.speed() != 0) {
+    set_speed(from.speed());
+  }
+  if (from.protocol() != 0) {
+    set_protocol(from.protocol());
+  }
+}
+
+void PortComponentAttributes::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.PortComponentAttributes)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void PortComponentAttributes::CopyFrom(const PortComponentAttributes& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.PortComponentAttributes)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool PortComponentAttributes::IsInitialized() const {
+  return true;
+}
+
+void PortComponentAttributes::Swap(PortComponentAttributes* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void PortComponentAttributes::InternalSwap(PortComponentAttributes* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  physical_label_.Swap(&other->physical_label_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(connector_type_, other->connector_type_);
+  swap(speed_, other->speed_);
+  swap(protocol_, other->protocol_);
+}
+
+::google::protobuf::Metadata PortComponentAttributes::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_2eproto);
+  return ::file_level_metadata_dmi_2fhw_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ContainerComponentAttributes::InitAsDefaultInstance() {
+}
+class ContainerComponentAttributes::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ContainerComponentAttributes::kPhysicalLabelFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ContainerComponentAttributes::ContainerComponentAttributes()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ContainerComponentAttributes)
+}
+ContainerComponentAttributes::ContainerComponentAttributes(const ContainerComponentAttributes& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  physical_label_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.physical_label().size() > 0) {
+    physical_label_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.physical_label_);
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.ContainerComponentAttributes)
+}
+
+void ContainerComponentAttributes::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ContainerComponentAttributes_dmi_2fhw_2eproto.base);
+  physical_label_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+ContainerComponentAttributes::~ContainerComponentAttributes() {
+  // @@protoc_insertion_point(destructor:dmi.ContainerComponentAttributes)
+  SharedDtor();
+}
+
+void ContainerComponentAttributes::SharedDtor() {
+  physical_label_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void ContainerComponentAttributes::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ContainerComponentAttributes& ContainerComponentAttributes::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ContainerComponentAttributes_dmi_2fhw_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ContainerComponentAttributes::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ContainerComponentAttributes)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  physical_label_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ContainerComponentAttributes::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ContainerComponentAttributes*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // string physical_label = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ContainerComponentAttributes.physical_label");
+        object = msg->mutable_physical_label();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ContainerComponentAttributes::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ContainerComponentAttributes)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // string physical_label = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_physical_label()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->physical_label().data(), static_cast<int>(this->physical_label().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ContainerComponentAttributes.physical_label"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ContainerComponentAttributes)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ContainerComponentAttributes)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ContainerComponentAttributes::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ContainerComponentAttributes)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string physical_label = 1;
+  if (this->physical_label().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->physical_label().data(), static_cast<int>(this->physical_label().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ContainerComponentAttributes.physical_label");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->physical_label(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ContainerComponentAttributes)
+}
+
+::google::protobuf::uint8* ContainerComponentAttributes::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ContainerComponentAttributes)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string physical_label = 1;
+  if (this->physical_label().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->physical_label().data(), static_cast<int>(this->physical_label().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ContainerComponentAttributes.physical_label");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->physical_label(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ContainerComponentAttributes)
+  return target;
+}
+
+size_t ContainerComponentAttributes::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ContainerComponentAttributes)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string physical_label = 1;
+  if (this->physical_label().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->physical_label());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ContainerComponentAttributes::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ContainerComponentAttributes)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ContainerComponentAttributes* source =
+      ::google::protobuf::DynamicCastToGenerated<ContainerComponentAttributes>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ContainerComponentAttributes)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ContainerComponentAttributes)
+    MergeFrom(*source);
+  }
+}
+
+void ContainerComponentAttributes::MergeFrom(const ContainerComponentAttributes& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ContainerComponentAttributes)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.physical_label().size() > 0) {
+
+    physical_label_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.physical_label_);
+  }
+}
+
+void ContainerComponentAttributes::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ContainerComponentAttributes)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ContainerComponentAttributes::CopyFrom(const ContainerComponentAttributes& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ContainerComponentAttributes)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ContainerComponentAttributes::IsInitialized() const {
+  return true;
+}
+
+void ContainerComponentAttributes::Swap(ContainerComponentAttributes* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ContainerComponentAttributes::InternalSwap(ContainerComponentAttributes* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  physical_label_.Swap(&other->physical_label_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+}
+
+::google::protobuf::Metadata ContainerComponentAttributes::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_2eproto);
+  return ::file_level_metadata_dmi_2fhw_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void PsuComponentAttributes::InitAsDefaultInstance() {
+}
+class PsuComponentAttributes::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int PsuComponentAttributes::kSupportedVoltageFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+PsuComponentAttributes::PsuComponentAttributes()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.PsuComponentAttributes)
+}
+PsuComponentAttributes::PsuComponentAttributes(const PsuComponentAttributes& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  supported_voltage_ = from.supported_voltage_;
+  // @@protoc_insertion_point(copy_constructor:dmi.PsuComponentAttributes)
+}
+
+void PsuComponentAttributes::SharedCtor() {
+  supported_voltage_ = 0;
+}
+
+PsuComponentAttributes::~PsuComponentAttributes() {
+  // @@protoc_insertion_point(destructor:dmi.PsuComponentAttributes)
+  SharedDtor();
+}
+
+void PsuComponentAttributes::SharedDtor() {
+}
+
+void PsuComponentAttributes::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const PsuComponentAttributes& PsuComponentAttributes::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_PsuComponentAttributes_dmi_2fhw_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void PsuComponentAttributes::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.PsuComponentAttributes)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  supported_voltage_ = 0;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* PsuComponentAttributes::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<PsuComponentAttributes*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.PsuComponentAttributes.SupportedVoltage supported_voltage = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_supported_voltage(static_cast<::dmi::PsuComponentAttributes_SupportedVoltage>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool PsuComponentAttributes::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.PsuComponentAttributes)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.PsuComponentAttributes.SupportedVoltage supported_voltage = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_supported_voltage(static_cast< ::dmi::PsuComponentAttributes_SupportedVoltage >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.PsuComponentAttributes)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.PsuComponentAttributes)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void PsuComponentAttributes::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.PsuComponentAttributes)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.PsuComponentAttributes.SupportedVoltage supported_voltage = 1;
+  if (this->supported_voltage() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->supported_voltage(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.PsuComponentAttributes)
+}
+
+::google::protobuf::uint8* PsuComponentAttributes::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.PsuComponentAttributes)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.PsuComponentAttributes.SupportedVoltage supported_voltage = 1;
+  if (this->supported_voltage() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->supported_voltage(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.PsuComponentAttributes)
+  return target;
+}
+
+size_t PsuComponentAttributes::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.PsuComponentAttributes)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.PsuComponentAttributes.SupportedVoltage supported_voltage = 1;
+  if (this->supported_voltage() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->supported_voltage());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void PsuComponentAttributes::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.PsuComponentAttributes)
+  GOOGLE_DCHECK_NE(&from, this);
+  const PsuComponentAttributes* source =
+      ::google::protobuf::DynamicCastToGenerated<PsuComponentAttributes>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.PsuComponentAttributes)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.PsuComponentAttributes)
+    MergeFrom(*source);
+  }
+}
+
+void PsuComponentAttributes::MergeFrom(const PsuComponentAttributes& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.PsuComponentAttributes)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.supported_voltage() != 0) {
+    set_supported_voltage(from.supported_voltage());
+  }
+}
+
+void PsuComponentAttributes::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.PsuComponentAttributes)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void PsuComponentAttributes::CopyFrom(const PsuComponentAttributes& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.PsuComponentAttributes)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool PsuComponentAttributes::IsInitialized() const {
+  return true;
+}
+
+void PsuComponentAttributes::Swap(PsuComponentAttributes* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void PsuComponentAttributes::InternalSwap(PsuComponentAttributes* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(supported_voltage_, other->supported_voltage_);
+}
+
+::google::protobuf::Metadata PsuComponentAttributes::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_2eproto);
+  return ::file_level_metadata_dmi_2fhw_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void TransceiverComponentsAttributes::InitAsDefaultInstance() {
+}
+class TransceiverComponentsAttributes::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int TransceiverComponentsAttributes::kFormFactorFieldNumber;
+const int TransceiverComponentsAttributes::kTransTypeFieldNumber;
+const int TransceiverComponentsAttributes::kMaxDistanceFieldNumber;
+const int TransceiverComponentsAttributes::kMaxDistanceScaleFieldNumber;
+const int TransceiverComponentsAttributes::kRxWavelengthFieldNumber;
+const int TransceiverComponentsAttributes::kTxWavelengthFieldNumber;
+const int TransceiverComponentsAttributes::kWavelengthScaleFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+TransceiverComponentsAttributes::TransceiverComponentsAttributes()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.TransceiverComponentsAttributes)
+}
+TransceiverComponentsAttributes::TransceiverComponentsAttributes(const TransceiverComponentsAttributes& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr),
+      rx_wavelength_(from.rx_wavelength_),
+      tx_wavelength_(from.tx_wavelength_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::memcpy(&form_factor_, &from.form_factor_,
+    static_cast<size_t>(reinterpret_cast<char*>(&wavelength_scale_) -
+    reinterpret_cast<char*>(&form_factor_)) + sizeof(wavelength_scale_));
+  // @@protoc_insertion_point(copy_constructor:dmi.TransceiverComponentsAttributes)
+}
+
+void TransceiverComponentsAttributes::SharedCtor() {
+  ::memset(&form_factor_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&wavelength_scale_) -
+      reinterpret_cast<char*>(&form_factor_)) + sizeof(wavelength_scale_));
+}
+
+TransceiverComponentsAttributes::~TransceiverComponentsAttributes() {
+  // @@protoc_insertion_point(destructor:dmi.TransceiverComponentsAttributes)
+  SharedDtor();
+}
+
+void TransceiverComponentsAttributes::SharedDtor() {
+}
+
+void TransceiverComponentsAttributes::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const TransceiverComponentsAttributes& TransceiverComponentsAttributes::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_TransceiverComponentsAttributes_dmi_2fhw_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void TransceiverComponentsAttributes::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.TransceiverComponentsAttributes)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  rx_wavelength_.Clear();
+  tx_wavelength_.Clear();
+  ::memset(&form_factor_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&wavelength_scale_) -
+      reinterpret_cast<char*>(&form_factor_)) + sizeof(wavelength_scale_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* TransceiverComponentsAttributes::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<TransceiverComponentsAttributes*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.TransceiverComponentsAttributes.FormFactor form_factor = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_form_factor(static_cast<::dmi::TransceiverComponentsAttributes_FormFactor>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.TransceiverComponentsAttributes.Type trans_type = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_trans_type(static_cast<::dmi::TransceiverComponentsAttributes_Type>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // uint32 max_distance = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
+        msg->set_max_distance(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ValueScale max_distance_scale = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 32) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_max_distance_scale(static_cast<::dmi::ValueScale>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // repeated uint32 rx_wavelength = 5;
+      case 5: {
+        if (static_cast<::google::protobuf::uint8>(tag) == 42) {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          parser_till_end = ::google::protobuf::internal::PackedUInt32Parser;
+          object = msg->mutable_rx_wavelength();
+          if (size > end - ptr) goto len_delim_till_end;
+          auto newend = ptr + size;
+          if (size) ptr = parser_till_end(ptr, newend, object, ctx);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend);
+          break;
+        } else if (static_cast<::google::protobuf::uint8>(tag) != 40) goto handle_unusual;
+        do {
+          msg->add_rx_wavelength(::google::protobuf::internal::ReadVarint(&ptr));
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 40 && (ptr += 1));
+        break;
+      }
+      // repeated uint32 tx_wavelength = 6;
+      case 6: {
+        if (static_cast<::google::protobuf::uint8>(tag) == 50) {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          parser_till_end = ::google::protobuf::internal::PackedUInt32Parser;
+          object = msg->mutable_tx_wavelength();
+          if (size > end - ptr) goto len_delim_till_end;
+          auto newend = ptr + size;
+          if (size) ptr = parser_till_end(ptr, newend, object, ctx);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend);
+          break;
+        } else if (static_cast<::google::protobuf::uint8>(tag) != 48) goto handle_unusual;
+        do {
+          msg->add_tx_wavelength(::google::protobuf::internal::ReadVarint(&ptr));
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 48 && (ptr += 1));
+        break;
+      }
+      // .dmi.ValueScale wavelength_scale = 7;
+      case 7: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 56) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_wavelength_scale(static_cast<::dmi::ValueScale>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool TransceiverComponentsAttributes::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.TransceiverComponentsAttributes)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.TransceiverComponentsAttributes.FormFactor form_factor = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_form_factor(static_cast< ::dmi::TransceiverComponentsAttributes_FormFactor >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.TransceiverComponentsAttributes.Type trans_type = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_trans_type(static_cast< ::dmi::TransceiverComponentsAttributes_Type >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // uint32 max_distance = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
+
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &max_distance_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ValueScale max_distance_scale = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (32 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_max_distance_scale(static_cast< ::dmi::ValueScale >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // repeated uint32 rx_wavelength = 5;
+      case 5: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (42 & 0xFF)) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, this->mutable_rx_wavelength())));
+        } else if (static_cast< ::google::protobuf::uint8>(tag) == (40 & 0xFF)) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 1, 42u, input, this->mutable_rx_wavelength())));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // repeated uint32 tx_wavelength = 6;
+      case 6: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (50 & 0xFF)) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, this->mutable_tx_wavelength())));
+        } else if (static_cast< ::google::protobuf::uint8>(tag) == (48 & 0xFF)) {
+          DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 1, 50u, input, this->mutable_tx_wavelength())));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ValueScale wavelength_scale = 7;
+      case 7: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (56 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_wavelength_scale(static_cast< ::dmi::ValueScale >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.TransceiverComponentsAttributes)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.TransceiverComponentsAttributes)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void TransceiverComponentsAttributes::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.TransceiverComponentsAttributes)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.TransceiverComponentsAttributes.FormFactor form_factor = 1;
+  if (this->form_factor() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->form_factor(), output);
+  }
+
+  // .dmi.TransceiverComponentsAttributes.Type trans_type = 2;
+  if (this->trans_type() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->trans_type(), output);
+  }
+
+  // uint32 max_distance = 3;
+  if (this->max_distance() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(3, this->max_distance(), output);
+  }
+
+  // .dmi.ValueScale max_distance_scale = 4;
+  if (this->max_distance_scale() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      4, this->max_distance_scale(), output);
+  }
+
+  // repeated uint32 rx_wavelength = 5;
+  if (this->rx_wavelength_size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteTag(5, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
+    output->WriteVarint32(_rx_wavelength_cached_byte_size_.load(
+        std::memory_order_relaxed));
+  }
+  for (int i = 0, n = this->rx_wavelength_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32NoTag(
+      this->rx_wavelength(i), output);
+  }
+
+  // repeated uint32 tx_wavelength = 6;
+  if (this->tx_wavelength_size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteTag(6, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
+    output->WriteVarint32(_tx_wavelength_cached_byte_size_.load(
+        std::memory_order_relaxed));
+  }
+  for (int i = 0, n = this->tx_wavelength_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32NoTag(
+      this->tx_wavelength(i), output);
+  }
+
+  // .dmi.ValueScale wavelength_scale = 7;
+  if (this->wavelength_scale() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      7, this->wavelength_scale(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.TransceiverComponentsAttributes)
+}
+
+::google::protobuf::uint8* TransceiverComponentsAttributes::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.TransceiverComponentsAttributes)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.TransceiverComponentsAttributes.FormFactor form_factor = 1;
+  if (this->form_factor() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->form_factor(), target);
+  }
+
+  // .dmi.TransceiverComponentsAttributes.Type trans_type = 2;
+  if (this->trans_type() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->trans_type(), target);
+  }
+
+  // uint32 max_distance = 3;
+  if (this->max_distance() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(3, this->max_distance(), target);
+  }
+
+  // .dmi.ValueScale max_distance_scale = 4;
+  if (this->max_distance_scale() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      4, this->max_distance_scale(), target);
+  }
+
+  // repeated uint32 rx_wavelength = 5;
+  if (this->rx_wavelength_size() > 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
+      5,
+      ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+      target);
+    target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
+        _rx_wavelength_cached_byte_size_.load(std::memory_order_relaxed),
+         target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteUInt32NoTagToArray(this->rx_wavelength_, target);
+  }
+
+  // repeated uint32 tx_wavelength = 6;
+  if (this->tx_wavelength_size() > 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(
+      6,
+      ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+      target);
+    target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
+        _tx_wavelength_cached_byte_size_.load(std::memory_order_relaxed),
+         target);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteUInt32NoTagToArray(this->tx_wavelength_, target);
+  }
+
+  // .dmi.ValueScale wavelength_scale = 7;
+  if (this->wavelength_scale() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      7, this->wavelength_scale(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.TransceiverComponentsAttributes)
+  return target;
+}
+
+size_t TransceiverComponentsAttributes::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.TransceiverComponentsAttributes)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated uint32 rx_wavelength = 5;
+  {
+    size_t data_size = ::google::protobuf::internal::WireFormatLite::
+      UInt32Size(this->rx_wavelength_);
+    if (data_size > 0) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+            static_cast<::google::protobuf::int32>(data_size));
+    }
+    int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);
+    _rx_wavelength_cached_byte_size_.store(cached_size,
+                                    std::memory_order_relaxed);
+    total_size += data_size;
+  }
+
+  // repeated uint32 tx_wavelength = 6;
+  {
+    size_t data_size = ::google::protobuf::internal::WireFormatLite::
+      UInt32Size(this->tx_wavelength_);
+    if (data_size > 0) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+            static_cast<::google::protobuf::int32>(data_size));
+    }
+    int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);
+    _tx_wavelength_cached_byte_size_.store(cached_size,
+                                    std::memory_order_relaxed);
+    total_size += data_size;
+  }
+
+  // .dmi.TransceiverComponentsAttributes.FormFactor form_factor = 1;
+  if (this->form_factor() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->form_factor());
+  }
+
+  // .dmi.TransceiverComponentsAttributes.Type trans_type = 2;
+  if (this->trans_type() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->trans_type());
+  }
+
+  // uint32 max_distance = 3;
+  if (this->max_distance() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::UInt32Size(
+        this->max_distance());
+  }
+
+  // .dmi.ValueScale max_distance_scale = 4;
+  if (this->max_distance_scale() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->max_distance_scale());
+  }
+
+  // .dmi.ValueScale wavelength_scale = 7;
+  if (this->wavelength_scale() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->wavelength_scale());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void TransceiverComponentsAttributes::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.TransceiverComponentsAttributes)
+  GOOGLE_DCHECK_NE(&from, this);
+  const TransceiverComponentsAttributes* source =
+      ::google::protobuf::DynamicCastToGenerated<TransceiverComponentsAttributes>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.TransceiverComponentsAttributes)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.TransceiverComponentsAttributes)
+    MergeFrom(*source);
+  }
+}
+
+void TransceiverComponentsAttributes::MergeFrom(const TransceiverComponentsAttributes& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.TransceiverComponentsAttributes)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  rx_wavelength_.MergeFrom(from.rx_wavelength_);
+  tx_wavelength_.MergeFrom(from.tx_wavelength_);
+  if (from.form_factor() != 0) {
+    set_form_factor(from.form_factor());
+  }
+  if (from.trans_type() != 0) {
+    set_trans_type(from.trans_type());
+  }
+  if (from.max_distance() != 0) {
+    set_max_distance(from.max_distance());
+  }
+  if (from.max_distance_scale() != 0) {
+    set_max_distance_scale(from.max_distance_scale());
+  }
+  if (from.wavelength_scale() != 0) {
+    set_wavelength_scale(from.wavelength_scale());
+  }
+}
+
+void TransceiverComponentsAttributes::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.TransceiverComponentsAttributes)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void TransceiverComponentsAttributes::CopyFrom(const TransceiverComponentsAttributes& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.TransceiverComponentsAttributes)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool TransceiverComponentsAttributes::IsInitialized() const {
+  return true;
+}
+
+void TransceiverComponentsAttributes::Swap(TransceiverComponentsAttributes* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void TransceiverComponentsAttributes::InternalSwap(TransceiverComponentsAttributes* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  rx_wavelength_.InternalSwap(&other->rx_wavelength_);
+  tx_wavelength_.InternalSwap(&other->tx_wavelength_);
+  swap(form_factor_, other->form_factor_);
+  swap(trans_type_, other->trans_type_);
+  swap(max_distance_, other->max_distance_);
+  swap(max_distance_scale_, other->max_distance_scale_);
+  swap(wavelength_scale_, other->wavelength_scale_);
+}
+
+::google::protobuf::Metadata TransceiverComponentsAttributes::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_2eproto);
+  return ::file_level_metadata_dmi_2fhw_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void Component::InitAsDefaultInstance() {
+  ::dmi::_Component_default_instance_._instance.get_mutable()->mfg_date_ = const_cast< ::google::protobuf::Timestamp*>(
+      ::google::protobuf::Timestamp::internal_default_instance());
+  ::dmi::_Component_default_instance_._instance.get_mutable()->uri_ = const_cast< ::dmi::Uri*>(
+      ::dmi::Uri::internal_default_instance());
+  ::dmi::_Component_default_instance_._instance.get_mutable()->uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+  ::dmi::_Component_default_instance_._instance.get_mutable()->state_ = const_cast< ::dmi::ComponentState*>(
+      ::dmi::ComponentState::internal_default_instance());
+  ::dmi::_Component_default_instance_.port_attr_ = const_cast< ::dmi::PortComponentAttributes*>(
+      ::dmi::PortComponentAttributes::internal_default_instance());
+  ::dmi::_Component_default_instance_.container_attr_ = const_cast< ::dmi::ContainerComponentAttributes*>(
+      ::dmi::ContainerComponentAttributes::internal_default_instance());
+  ::dmi::_Component_default_instance_.psu_attr_ = const_cast< ::dmi::PsuComponentAttributes*>(
+      ::dmi::PsuComponentAttributes::internal_default_instance());
+  ::dmi::_Component_default_instance_.transceiver_attr_ = const_cast< ::dmi::TransceiverComponentsAttributes*>(
+      ::dmi::TransceiverComponentsAttributes::internal_default_instance());
+}
+class Component::HasBitSetters {
+ public:
+  static const ::google::protobuf::Timestamp& mfg_date(const Component* msg);
+  static const ::dmi::Uri& uri(const Component* msg);
+  static const ::dmi::Uuid& uuid(const Component* msg);
+  static const ::dmi::ComponentState& state(const Component* msg);
+  static const ::dmi::PortComponentAttributes& port_attr(const Component* msg);
+  static const ::dmi::ContainerComponentAttributes& container_attr(const Component* msg);
+  static const ::dmi::PsuComponentAttributes& psu_attr(const Component* msg);
+  static const ::dmi::TransceiverComponentsAttributes& transceiver_attr(const Component* msg);
+};
+
+const ::google::protobuf::Timestamp&
+Component::HasBitSetters::mfg_date(const Component* msg) {
+  return *msg->mfg_date_;
+}
+const ::dmi::Uri&
+Component::HasBitSetters::uri(const Component* msg) {
+  return *msg->uri_;
+}
+const ::dmi::Uuid&
+Component::HasBitSetters::uuid(const Component* msg) {
+  return *msg->uuid_;
+}
+const ::dmi::ComponentState&
+Component::HasBitSetters::state(const Component* msg) {
+  return *msg->state_;
+}
+const ::dmi::PortComponentAttributes&
+Component::HasBitSetters::port_attr(const Component* msg) {
+  return *msg->specific_.port_attr_;
+}
+const ::dmi::ContainerComponentAttributes&
+Component::HasBitSetters::container_attr(const Component* msg) {
+  return *msg->specific_.container_attr_;
+}
+const ::dmi::PsuComponentAttributes&
+Component::HasBitSetters::psu_attr(const Component* msg) {
+  return *msg->specific_.psu_attr_;
+}
+const ::dmi::TransceiverComponentsAttributes&
+Component::HasBitSetters::transceiver_attr(const Component* msg) {
+  return *msg->specific_.transceiver_attr_;
+}
+void Component::clear_mfg_date() {
+  if (GetArenaNoVirtual() == nullptr && mfg_date_ != nullptr) {
+    delete mfg_date_;
+  }
+  mfg_date_ = nullptr;
+}
+void Component::set_allocated_port_attr(::dmi::PortComponentAttributes* port_attr) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  clear_specific();
+  if (port_attr) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      port_attr = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, port_attr, submessage_arena);
+    }
+    set_has_port_attr();
+    specific_.port_attr_ = port_attr;
+  }
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.port_attr)
+}
+void Component::set_allocated_container_attr(::dmi::ContainerComponentAttributes* container_attr) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  clear_specific();
+  if (container_attr) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      container_attr = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, container_attr, submessage_arena);
+    }
+    set_has_container_attr();
+    specific_.container_attr_ = container_attr;
+  }
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.container_attr)
+}
+void Component::set_allocated_psu_attr(::dmi::PsuComponentAttributes* psu_attr) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  clear_specific();
+  if (psu_attr) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      psu_attr = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, psu_attr, submessage_arena);
+    }
+    set_has_psu_attr();
+    specific_.psu_attr_ = psu_attr;
+  }
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.psu_attr)
+}
+void Component::set_allocated_transceiver_attr(::dmi::TransceiverComponentsAttributes* transceiver_attr) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  clear_specific();
+  if (transceiver_attr) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      transceiver_attr = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, transceiver_attr, submessage_arena);
+    }
+    set_has_transceiver_attr();
+    specific_.transceiver_attr_ = transceiver_attr;
+  }
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.transceiver_attr)
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Component::kNameFieldNumber;
+const int Component::kClassFieldNumber;
+const int Component::kDescriptionFieldNumber;
+const int Component::kParentFieldNumber;
+const int Component::kParentRelPosFieldNumber;
+const int Component::kChildrenFieldNumber;
+const int Component::kHardwareRevFieldNumber;
+const int Component::kFirmwareRevFieldNumber;
+const int Component::kSoftwareRevFieldNumber;
+const int Component::kSerialNumFieldNumber;
+const int Component::kMfgNameFieldNumber;
+const int Component::kModelNameFieldNumber;
+const int Component::kAliasFieldNumber;
+const int Component::kAssetIdFieldNumber;
+const int Component::kIsFruFieldNumber;
+const int Component::kMfgDateFieldNumber;
+const int Component::kUriFieldNumber;
+const int Component::kUuidFieldNumber;
+const int Component::kStateFieldNumber;
+const int Component::kSensorDataFieldNumber;
+const int Component::kPortAttrFieldNumber;
+const int Component::kContainerAttrFieldNumber;
+const int Component::kPsuAttrFieldNumber;
+const int Component::kTransceiverAttrFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Component::Component()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.Component)
+}
+Component::Component(const Component& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr),
+      children_(from.children_),
+      sensor_data_(from.sensor_data_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.name().size() > 0) {
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  description_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.description().size() > 0) {
+    description_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.description_);
+  }
+  parent_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.parent().size() > 0) {
+    parent_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.parent_);
+  }
+  hardware_rev_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.hardware_rev().size() > 0) {
+    hardware_rev_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.hardware_rev_);
+  }
+  firmware_rev_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.firmware_rev().size() > 0) {
+    firmware_rev_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.firmware_rev_);
+  }
+  software_rev_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.software_rev().size() > 0) {
+    software_rev_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.software_rev_);
+  }
+  serial_num_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.serial_num().size() > 0) {
+    serial_num_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.serial_num_);
+  }
+  mfg_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.mfg_name().size() > 0) {
+    mfg_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.mfg_name_);
+  }
+  model_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.model_name().size() > 0) {
+    model_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.model_name_);
+  }
+  alias_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.alias().size() > 0) {
+    alias_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.alias_);
+  }
+  asset_id_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.asset_id().size() > 0) {
+    asset_id_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.asset_id_);
+  }
+  if (from.has_mfg_date()) {
+    mfg_date_ = new ::google::protobuf::Timestamp(*from.mfg_date_);
+  } else {
+    mfg_date_ = nullptr;
+  }
+  if (from.has_uri()) {
+    uri_ = new ::dmi::Uri(*from.uri_);
+  } else {
+    uri_ = nullptr;
+  }
+  if (from.has_uuid()) {
+    uuid_ = new ::dmi::Uuid(*from.uuid_);
+  } else {
+    uuid_ = nullptr;
+  }
+  if (from.has_state()) {
+    state_ = new ::dmi::ComponentState(*from.state_);
+  } else {
+    state_ = nullptr;
+  }
+  ::memcpy(&class__, &from.class__,
+    static_cast<size_t>(reinterpret_cast<char*>(&is_fru_) -
+    reinterpret_cast<char*>(&class__)) + sizeof(is_fru_));
+  clear_has_specific();
+  switch (from.specific_case()) {
+    case kPortAttr: {
+      mutable_port_attr()->::dmi::PortComponentAttributes::MergeFrom(from.port_attr());
+      break;
+    }
+    case kContainerAttr: {
+      mutable_container_attr()->::dmi::ContainerComponentAttributes::MergeFrom(from.container_attr());
+      break;
+    }
+    case kPsuAttr: {
+      mutable_psu_attr()->::dmi::PsuComponentAttributes::MergeFrom(from.psu_attr());
+      break;
+    }
+    case kTransceiverAttr: {
+      mutable_transceiver_attr()->::dmi::TransceiverComponentsAttributes::MergeFrom(from.transceiver_attr());
+      break;
+    }
+    case SPECIFIC_NOT_SET: {
+      break;
+    }
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.Component)
+}
+
+void Component::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_Component_dmi_2fhw_2eproto.base);
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  description_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  parent_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  hardware_rev_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  firmware_rev_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  software_rev_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  serial_num_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  mfg_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  model_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  alias_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  asset_id_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&mfg_date_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&is_fru_) -
+      reinterpret_cast<char*>(&mfg_date_)) + sizeof(is_fru_));
+  clear_has_specific();
+}
+
+Component::~Component() {
+  // @@protoc_insertion_point(destructor:dmi.Component)
+  SharedDtor();
+}
+
+void Component::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  description_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  parent_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  hardware_rev_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  firmware_rev_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  software_rev_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  serial_num_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  mfg_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  model_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  alias_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  asset_id_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete mfg_date_;
+  if (this != internal_default_instance()) delete uri_;
+  if (this != internal_default_instance()) delete uuid_;
+  if (this != internal_default_instance()) delete state_;
+  if (has_specific()) {
+    clear_specific();
+  }
+}
+
+void Component::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const Component& Component::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_Component_dmi_2fhw_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void Component::clear_specific() {
+// @@protoc_insertion_point(one_of_clear_start:dmi.Component)
+  switch (specific_case()) {
+    case kPortAttr: {
+      delete specific_.port_attr_;
+      break;
+    }
+    case kContainerAttr: {
+      delete specific_.container_attr_;
+      break;
+    }
+    case kPsuAttr: {
+      delete specific_.psu_attr_;
+      break;
+    }
+    case kTransceiverAttr: {
+      delete specific_.transceiver_attr_;
+      break;
+    }
+    case SPECIFIC_NOT_SET: {
+      break;
+    }
+  }
+  _oneof_case_[0] = SPECIFIC_NOT_SET;
+}
+
+
+void Component::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.Component)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  children_.Clear();
+  sensor_data_.Clear();
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  description_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  parent_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  hardware_rev_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  firmware_rev_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  software_rev_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  serial_num_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  mfg_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  model_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  alias_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  asset_id_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && mfg_date_ != nullptr) {
+    delete mfg_date_;
+  }
+  mfg_date_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && uri_ != nullptr) {
+    delete uri_;
+  }
+  uri_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && uuid_ != nullptr) {
+    delete uuid_;
+  }
+  uuid_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && state_ != nullptr) {
+    delete state_;
+  }
+  state_ = nullptr;
+  ::memset(&class__, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&is_fru_) -
+      reinterpret_cast<char*>(&class__)) + sizeof(is_fru_));
+  clear_specific();
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* Component::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<Component*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // string name = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Component.name");
+        object = msg->mutable_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // .dmi.ComponentType class = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_class_(static_cast<::dmi::ComponentType>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string description = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Component.description");
+        object = msg->mutable_description();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string parent = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Component.parent");
+        object = msg->mutable_parent();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // int32 parent_rel_pos = 5;
+      case 5: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 40) goto handle_unusual;
+        msg->set_parent_rel_pos(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // repeated .dmi.Component children = 6;
+      case 6: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 50) goto handle_unusual;
+        do {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          parser_till_end = ::dmi::Component::_InternalParse;
+          object = msg->add_children();
+          if (size > end - ptr) goto len_delim_till_end;
+          ptr += size;
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+              {parser_till_end, object}, ptr - size, ptr));
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 50 && (ptr += 1));
+        break;
+      }
+      // string hardware_rev = 7;
+      case 7: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Component.hardware_rev");
+        object = msg->mutable_hardware_rev();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string firmware_rev = 8;
+      case 8: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 66) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Component.firmware_rev");
+        object = msg->mutable_firmware_rev();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string software_rev = 9;
+      case 9: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 74) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Component.software_rev");
+        object = msg->mutable_software_rev();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string serial_num = 10;
+      case 10: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 82) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Component.serial_num");
+        object = msg->mutable_serial_num();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string mfg_name = 11;
+      case 11: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 90) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Component.mfg_name");
+        object = msg->mutable_mfg_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string model_name = 12;
+      case 12: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 98) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Component.model_name");
+        object = msg->mutable_model_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string alias = 13;
+      case 13: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 106) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Component.alias");
+        object = msg->mutable_alias();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string asset_id = 14;
+      case 14: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 114) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Component.asset_id");
+        object = msg->mutable_asset_id();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // bool is_fru = 15;
+      case 15: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 120) goto handle_unusual;
+        msg->set_is_fru(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .google.protobuf.Timestamp mfg_date = 16;
+      case 16: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 130) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::google::protobuf::Timestamp::_InternalParse;
+        object = msg->mutable_mfg_date();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.Uri uri = 17;
+      case 17: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 138) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uri::_InternalParse;
+        object = msg->mutable_uri();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.Uuid uuid = 18;
+      case 18: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 146) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.ComponentState state = 19;
+      case 19: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 154) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::ComponentState::_InternalParse;
+        object = msg->mutable_state();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // repeated .dmi.ComponentSensorData sensor_data = 20;
+      case 20: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 162) goto handle_unusual;
+        do {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          parser_till_end = ::dmi::ComponentSensorData::_InternalParse;
+          object = msg->add_sensor_data();
+          if (size > end - ptr) goto len_delim_till_end;
+          ptr += size;
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+              {parser_till_end, object}, ptr - size, ptr));
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 65535) == 418 && (ptr += 2));
+        break;
+      }
+      // .dmi.PortComponentAttributes port_attr = 50;
+      case 50: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 146) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::PortComponentAttributes::_InternalParse;
+        object = msg->mutable_port_attr();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.ContainerComponentAttributes container_attr = 51;
+      case 51: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 154) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::ContainerComponentAttributes::_InternalParse;
+        object = msg->mutable_container_attr();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.PsuComponentAttributes psu_attr = 52;
+      case 52: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 162) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::PsuComponentAttributes::_InternalParse;
+        object = msg->mutable_psu_attr();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.TransceiverComponentsAttributes transceiver_attr = 53;
+      case 53: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 170) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::TransceiverComponentsAttributes::_InternalParse;
+        object = msg->mutable_transceiver_attr();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool Component::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.Component)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(16383u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // string name = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->name().data(), static_cast<int>(this->name().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Component.name"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ComponentType class = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_class_(static_cast< ::dmi::ComponentType >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string description = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_description()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->description().data(), static_cast<int>(this->description().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Component.description"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string parent = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_parent()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->parent().data(), static_cast<int>(this->parent().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Component.parent"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // int32 parent_rel_pos = 5;
+      case 5: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (40 & 0xFF)) {
+
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &parent_rel_pos_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // repeated .dmi.Component children = 6;
+      case 6: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (50 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+                input, add_children()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string hardware_rev = 7;
+      case 7: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (58 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_hardware_rev()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->hardware_rev().data(), static_cast<int>(this->hardware_rev().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Component.hardware_rev"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string firmware_rev = 8;
+      case 8: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (66 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_firmware_rev()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->firmware_rev().data(), static_cast<int>(this->firmware_rev().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Component.firmware_rev"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string software_rev = 9;
+      case 9: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (74 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_software_rev()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->software_rev().data(), static_cast<int>(this->software_rev().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Component.software_rev"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string serial_num = 10;
+      case 10: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (82 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_serial_num()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->serial_num().data(), static_cast<int>(this->serial_num().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Component.serial_num"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string mfg_name = 11;
+      case 11: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (90 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_mfg_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->mfg_name().data(), static_cast<int>(this->mfg_name().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Component.mfg_name"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string model_name = 12;
+      case 12: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (98 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_model_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->model_name().data(), static_cast<int>(this->model_name().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Component.model_name"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string alias = 13;
+      case 13: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (106 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_alias()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->alias().data(), static_cast<int>(this->alias().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Component.alias"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string asset_id = 14;
+      case 14: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (114 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_asset_id()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->asset_id().data(), static_cast<int>(this->asset_id().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Component.asset_id"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // bool is_fru = 15;
+      case 15: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (120 & 0xFF)) {
+
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &is_fru_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .google.protobuf.Timestamp mfg_date = 16;
+      case 16: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (130 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_mfg_date()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Uri uri = 17;
+      case 17: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (138 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_uri()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Uuid uuid = 18;
+      case 18: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (146 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ComponentState state = 19;
+      case 19: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (154 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_state()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // repeated .dmi.ComponentSensorData sensor_data = 20;
+      case 20: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (162 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+                input, add_sensor_data()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.PortComponentAttributes port_attr = 50;
+      case 50: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (402 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_port_attr()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ContainerComponentAttributes container_attr = 51;
+      case 51: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (410 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_container_attr()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.PsuComponentAttributes psu_attr = 52;
+      case 52: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (418 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_psu_attr()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.TransceiverComponentsAttributes transceiver_attr = 53;
+      case 53: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (426 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_transceiver_attr()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.Component)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.Component)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void Component::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.Component)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), static_cast<int>(this->name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // .dmi.ComponentType class = 2;
+  if (this->class_() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->class_(), output);
+  }
+
+  // string description = 3;
+  if (this->description().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->description().data(), static_cast<int>(this->description().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.description");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->description(), output);
+  }
+
+  // string parent = 4;
+  if (this->parent().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->parent().data(), static_cast<int>(this->parent().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.parent");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->parent(), output);
+  }
+
+  // int32 parent_rel_pos = 5;
+  if (this->parent_rel_pos() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(5, this->parent_rel_pos(), output);
+  }
+
+  // repeated .dmi.Component children = 6;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->children_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      6,
+      this->children(static_cast<int>(i)),
+      output);
+  }
+
+  // string hardware_rev = 7;
+  if (this->hardware_rev().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->hardware_rev().data(), static_cast<int>(this->hardware_rev().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.hardware_rev");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      7, this->hardware_rev(), output);
+  }
+
+  // string firmware_rev = 8;
+  if (this->firmware_rev().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->firmware_rev().data(), static_cast<int>(this->firmware_rev().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.firmware_rev");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      8, this->firmware_rev(), output);
+  }
+
+  // string software_rev = 9;
+  if (this->software_rev().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->software_rev().data(), static_cast<int>(this->software_rev().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.software_rev");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      9, this->software_rev(), output);
+  }
+
+  // string serial_num = 10;
+  if (this->serial_num().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->serial_num().data(), static_cast<int>(this->serial_num().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.serial_num");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      10, this->serial_num(), output);
+  }
+
+  // string mfg_name = 11;
+  if (this->mfg_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->mfg_name().data(), static_cast<int>(this->mfg_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.mfg_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      11, this->mfg_name(), output);
+  }
+
+  // string model_name = 12;
+  if (this->model_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->model_name().data(), static_cast<int>(this->model_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.model_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      12, this->model_name(), output);
+  }
+
+  // string alias = 13;
+  if (this->alias().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->alias().data(), static_cast<int>(this->alias().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.alias");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      13, this->alias(), output);
+  }
+
+  // string asset_id = 14;
+  if (this->asset_id().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->asset_id().data(), static_cast<int>(this->asset_id().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.asset_id");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      14, this->asset_id(), output);
+  }
+
+  // bool is_fru = 15;
+  if (this->is_fru() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(15, this->is_fru(), output);
+  }
+
+  // .google.protobuf.Timestamp mfg_date = 16;
+  if (this->has_mfg_date()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      16, HasBitSetters::mfg_date(this), output);
+  }
+
+  // .dmi.Uri uri = 17;
+  if (this->has_uri()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      17, HasBitSetters::uri(this), output);
+  }
+
+  // .dmi.Uuid uuid = 18;
+  if (this->has_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      18, HasBitSetters::uuid(this), output);
+  }
+
+  // .dmi.ComponentState state = 19;
+  if (this->has_state()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      19, HasBitSetters::state(this), output);
+  }
+
+  // repeated .dmi.ComponentSensorData sensor_data = 20;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->sensor_data_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      20,
+      this->sensor_data(static_cast<int>(i)),
+      output);
+  }
+
+  // .dmi.PortComponentAttributes port_attr = 50;
+  if (has_port_attr()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      50, HasBitSetters::port_attr(this), output);
+  }
+
+  // .dmi.ContainerComponentAttributes container_attr = 51;
+  if (has_container_attr()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      51, HasBitSetters::container_attr(this), output);
+  }
+
+  // .dmi.PsuComponentAttributes psu_attr = 52;
+  if (has_psu_attr()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      52, HasBitSetters::psu_attr(this), output);
+  }
+
+  // .dmi.TransceiverComponentsAttributes transceiver_attr = 53;
+  if (has_transceiver_attr()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      53, HasBitSetters::transceiver_attr(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.Component)
+}
+
+::google::protobuf::uint8* Component::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.Component)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), static_cast<int>(this->name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // .dmi.ComponentType class = 2;
+  if (this->class_() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->class_(), target);
+  }
+
+  // string description = 3;
+  if (this->description().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->description().data(), static_cast<int>(this->description().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.description");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->description(), target);
+  }
+
+  // string parent = 4;
+  if (this->parent().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->parent().data(), static_cast<int>(this->parent().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.parent");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->parent(), target);
+  }
+
+  // int32 parent_rel_pos = 5;
+  if (this->parent_rel_pos() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(5, this->parent_rel_pos(), target);
+  }
+
+  // repeated .dmi.Component children = 6;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->children_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        6, this->children(static_cast<int>(i)), target);
+  }
+
+  // string hardware_rev = 7;
+  if (this->hardware_rev().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->hardware_rev().data(), static_cast<int>(this->hardware_rev().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.hardware_rev");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        7, this->hardware_rev(), target);
+  }
+
+  // string firmware_rev = 8;
+  if (this->firmware_rev().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->firmware_rev().data(), static_cast<int>(this->firmware_rev().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.firmware_rev");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        8, this->firmware_rev(), target);
+  }
+
+  // string software_rev = 9;
+  if (this->software_rev().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->software_rev().data(), static_cast<int>(this->software_rev().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.software_rev");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        9, this->software_rev(), target);
+  }
+
+  // string serial_num = 10;
+  if (this->serial_num().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->serial_num().data(), static_cast<int>(this->serial_num().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.serial_num");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        10, this->serial_num(), target);
+  }
+
+  // string mfg_name = 11;
+  if (this->mfg_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->mfg_name().data(), static_cast<int>(this->mfg_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.mfg_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        11, this->mfg_name(), target);
+  }
+
+  // string model_name = 12;
+  if (this->model_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->model_name().data(), static_cast<int>(this->model_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.model_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        12, this->model_name(), target);
+  }
+
+  // string alias = 13;
+  if (this->alias().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->alias().data(), static_cast<int>(this->alias().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.alias");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        13, this->alias(), target);
+  }
+
+  // string asset_id = 14;
+  if (this->asset_id().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->asset_id().data(), static_cast<int>(this->asset_id().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Component.asset_id");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        14, this->asset_id(), target);
+  }
+
+  // bool is_fru = 15;
+  if (this->is_fru() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(15, this->is_fru(), target);
+  }
+
+  // .google.protobuf.Timestamp mfg_date = 16;
+  if (this->has_mfg_date()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        16, HasBitSetters::mfg_date(this), target);
+  }
+
+  // .dmi.Uri uri = 17;
+  if (this->has_uri()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        17, HasBitSetters::uri(this), target);
+  }
+
+  // .dmi.Uuid uuid = 18;
+  if (this->has_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        18, HasBitSetters::uuid(this), target);
+  }
+
+  // .dmi.ComponentState state = 19;
+  if (this->has_state()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        19, HasBitSetters::state(this), target);
+  }
+
+  // repeated .dmi.ComponentSensorData sensor_data = 20;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->sensor_data_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        20, this->sensor_data(static_cast<int>(i)), target);
+  }
+
+  // .dmi.PortComponentAttributes port_attr = 50;
+  if (has_port_attr()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        50, HasBitSetters::port_attr(this), target);
+  }
+
+  // .dmi.ContainerComponentAttributes container_attr = 51;
+  if (has_container_attr()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        51, HasBitSetters::container_attr(this), target);
+  }
+
+  // .dmi.PsuComponentAttributes psu_attr = 52;
+  if (has_psu_attr()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        52, HasBitSetters::psu_attr(this), target);
+  }
+
+  // .dmi.TransceiverComponentsAttributes transceiver_attr = 53;
+  if (has_transceiver_attr()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        53, HasBitSetters::transceiver_attr(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.Component)
+  return target;
+}
+
+size_t Component::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.Component)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated .dmi.Component children = 6;
+  {
+    unsigned int count = static_cast<unsigned int>(this->children_size());
+    total_size += 1UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->children(static_cast<int>(i)));
+    }
+  }
+
+  // repeated .dmi.ComponentSensorData sensor_data = 20;
+  {
+    unsigned int count = static_cast<unsigned int>(this->sensor_data_size());
+    total_size += 2UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->sensor_data(static_cast<int>(i)));
+    }
+  }
+
+  // string name = 1;
+  if (this->name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name());
+  }
+
+  // string description = 3;
+  if (this->description().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->description());
+  }
+
+  // string parent = 4;
+  if (this->parent().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->parent());
+  }
+
+  // string hardware_rev = 7;
+  if (this->hardware_rev().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->hardware_rev());
+  }
+
+  // string firmware_rev = 8;
+  if (this->firmware_rev().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->firmware_rev());
+  }
+
+  // string software_rev = 9;
+  if (this->software_rev().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->software_rev());
+  }
+
+  // string serial_num = 10;
+  if (this->serial_num().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->serial_num());
+  }
+
+  // string mfg_name = 11;
+  if (this->mfg_name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->mfg_name());
+  }
+
+  // string model_name = 12;
+  if (this->model_name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->model_name());
+  }
+
+  // string alias = 13;
+  if (this->alias().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->alias());
+  }
+
+  // string asset_id = 14;
+  if (this->asset_id().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->asset_id());
+  }
+
+  // .google.protobuf.Timestamp mfg_date = 16;
+  if (this->has_mfg_date()) {
+    total_size += 2 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *mfg_date_);
+  }
+
+  // .dmi.Uri uri = 17;
+  if (this->has_uri()) {
+    total_size += 2 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *uri_);
+  }
+
+  // .dmi.Uuid uuid = 18;
+  if (this->has_uuid()) {
+    total_size += 2 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *uuid_);
+  }
+
+  // .dmi.ComponentState state = 19;
+  if (this->has_state()) {
+    total_size += 2 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *state_);
+  }
+
+  // .dmi.ComponentType class = 2;
+  if (this->class_() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->class_());
+  }
+
+  // int32 parent_rel_pos = 5;
+  if (this->parent_rel_pos() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int32Size(
+        this->parent_rel_pos());
+  }
+
+  // bool is_fru = 15;
+  if (this->is_fru() != 0) {
+    total_size += 1 + 1;
+  }
+
+  switch (specific_case()) {
+    // .dmi.PortComponentAttributes port_attr = 50;
+    case kPortAttr: {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          *specific_.port_attr_);
+      break;
+    }
+    // .dmi.ContainerComponentAttributes container_attr = 51;
+    case kContainerAttr: {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          *specific_.container_attr_);
+      break;
+    }
+    // .dmi.PsuComponentAttributes psu_attr = 52;
+    case kPsuAttr: {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          *specific_.psu_attr_);
+      break;
+    }
+    // .dmi.TransceiverComponentsAttributes transceiver_attr = 53;
+    case kTransceiverAttr: {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          *specific_.transceiver_attr_);
+      break;
+    }
+    case SPECIFIC_NOT_SET: {
+      break;
+    }
+  }
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void Component::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.Component)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Component* source =
+      ::google::protobuf::DynamicCastToGenerated<Component>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.Component)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.Component)
+    MergeFrom(*source);
+  }
+}
+
+void Component::MergeFrom(const Component& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.Component)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  children_.MergeFrom(from.children_);
+  sensor_data_.MergeFrom(from.sensor_data_);
+  if (from.name().size() > 0) {
+
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  if (from.description().size() > 0) {
+
+    description_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.description_);
+  }
+  if (from.parent().size() > 0) {
+
+    parent_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.parent_);
+  }
+  if (from.hardware_rev().size() > 0) {
+
+    hardware_rev_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.hardware_rev_);
+  }
+  if (from.firmware_rev().size() > 0) {
+
+    firmware_rev_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.firmware_rev_);
+  }
+  if (from.software_rev().size() > 0) {
+
+    software_rev_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.software_rev_);
+  }
+  if (from.serial_num().size() > 0) {
+
+    serial_num_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.serial_num_);
+  }
+  if (from.mfg_name().size() > 0) {
+
+    mfg_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.mfg_name_);
+  }
+  if (from.model_name().size() > 0) {
+
+    model_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.model_name_);
+  }
+  if (from.alias().size() > 0) {
+
+    alias_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.alias_);
+  }
+  if (from.asset_id().size() > 0) {
+
+    asset_id_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.asset_id_);
+  }
+  if (from.has_mfg_date()) {
+    mutable_mfg_date()->::google::protobuf::Timestamp::MergeFrom(from.mfg_date());
+  }
+  if (from.has_uri()) {
+    mutable_uri()->::dmi::Uri::MergeFrom(from.uri());
+  }
+  if (from.has_uuid()) {
+    mutable_uuid()->::dmi::Uuid::MergeFrom(from.uuid());
+  }
+  if (from.has_state()) {
+    mutable_state()->::dmi::ComponentState::MergeFrom(from.state());
+  }
+  if (from.class_() != 0) {
+    set_class_(from.class_());
+  }
+  if (from.parent_rel_pos() != 0) {
+    set_parent_rel_pos(from.parent_rel_pos());
+  }
+  if (from.is_fru() != 0) {
+    set_is_fru(from.is_fru());
+  }
+  switch (from.specific_case()) {
+    case kPortAttr: {
+      mutable_port_attr()->::dmi::PortComponentAttributes::MergeFrom(from.port_attr());
+      break;
+    }
+    case kContainerAttr: {
+      mutable_container_attr()->::dmi::ContainerComponentAttributes::MergeFrom(from.container_attr());
+      break;
+    }
+    case kPsuAttr: {
+      mutable_psu_attr()->::dmi::PsuComponentAttributes::MergeFrom(from.psu_attr());
+      break;
+    }
+    case kTransceiverAttr: {
+      mutable_transceiver_attr()->::dmi::TransceiverComponentsAttributes::MergeFrom(from.transceiver_attr());
+      break;
+    }
+    case SPECIFIC_NOT_SET: {
+      break;
+    }
+  }
+}
+
+void Component::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.Component)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Component::CopyFrom(const Component& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.Component)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Component::IsInitialized() const {
+  return true;
+}
+
+void Component::Swap(Component* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Component::InternalSwap(Component* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  CastToBase(&children_)->InternalSwap(CastToBase(&other->children_));
+  CastToBase(&sensor_data_)->InternalSwap(CastToBase(&other->sensor_data_));
+  name_.Swap(&other->name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  description_.Swap(&other->description_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  parent_.Swap(&other->parent_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  hardware_rev_.Swap(&other->hardware_rev_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  firmware_rev_.Swap(&other->firmware_rev_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  software_rev_.Swap(&other->software_rev_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  serial_num_.Swap(&other->serial_num_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  mfg_name_.Swap(&other->mfg_name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  model_name_.Swap(&other->model_name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  alias_.Swap(&other->alias_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  asset_id_.Swap(&other->asset_id_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(mfg_date_, other->mfg_date_);
+  swap(uri_, other->uri_);
+  swap(uuid_, other->uuid_);
+  swap(state_, other->state_);
+  swap(class__, other->class__);
+  swap(parent_rel_pos_, other->parent_rel_pos_);
+  swap(is_fru_, other->is_fru_);
+  swap(specific_, other->specific_);
+  swap(_oneof_case_[0], other->_oneof_case_[0]);
+}
+
+::google::protobuf::Metadata Component::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_2eproto);
+  return ::file_level_metadata_dmi_2fhw_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void Hardware::InitAsDefaultInstance() {
+  ::dmi::_Hardware_default_instance_._instance.get_mutable()->last_change_ = const_cast< ::google::protobuf::Timestamp*>(
+      ::google::protobuf::Timestamp::internal_default_instance());
+  ::dmi::_Hardware_default_instance_._instance.get_mutable()->root_ = const_cast< ::dmi::Component*>(
+      ::dmi::Component::internal_default_instance());
+  ::dmi::_Hardware_default_instance_._instance.get_mutable()->last_booted_ = const_cast< ::google::protobuf::Timestamp*>(
+      ::google::protobuf::Timestamp::internal_default_instance());
+}
+class Hardware::HasBitSetters {
+ public:
+  static const ::google::protobuf::Timestamp& last_change(const Hardware* msg);
+  static const ::dmi::Component& root(const Hardware* msg);
+  static const ::google::protobuf::Timestamp& last_booted(const Hardware* msg);
+};
+
+const ::google::protobuf::Timestamp&
+Hardware::HasBitSetters::last_change(const Hardware* msg) {
+  return *msg->last_change_;
+}
+const ::dmi::Component&
+Hardware::HasBitSetters::root(const Hardware* msg) {
+  return *msg->root_;
+}
+const ::google::protobuf::Timestamp&
+Hardware::HasBitSetters::last_booted(const Hardware* msg) {
+  return *msg->last_booted_;
+}
+void Hardware::clear_last_change() {
+  if (GetArenaNoVirtual() == nullptr && last_change_ != nullptr) {
+    delete last_change_;
+  }
+  last_change_ = nullptr;
+}
+void Hardware::clear_last_booted() {
+  if (GetArenaNoVirtual() == nullptr && last_booted_ != nullptr) {
+    delete last_booted_;
+  }
+  last_booted_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Hardware::kLastChangeFieldNumber;
+const int Hardware::kRootFieldNumber;
+const int Hardware::kLastBootedFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Hardware::Hardware()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.Hardware)
+}
+Hardware::Hardware(const Hardware& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_last_change()) {
+    last_change_ = new ::google::protobuf::Timestamp(*from.last_change_);
+  } else {
+    last_change_ = nullptr;
+  }
+  if (from.has_root()) {
+    root_ = new ::dmi::Component(*from.root_);
+  } else {
+    root_ = nullptr;
+  }
+  if (from.has_last_booted()) {
+    last_booted_ = new ::google::protobuf::Timestamp(*from.last_booted_);
+  } else {
+    last_booted_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.Hardware)
+}
+
+void Hardware::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_Hardware_dmi_2fhw_2eproto.base);
+  ::memset(&last_change_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&last_booted_) -
+      reinterpret_cast<char*>(&last_change_)) + sizeof(last_booted_));
+}
+
+Hardware::~Hardware() {
+  // @@protoc_insertion_point(destructor:dmi.Hardware)
+  SharedDtor();
+}
+
+void Hardware::SharedDtor() {
+  if (this != internal_default_instance()) delete last_change_;
+  if (this != internal_default_instance()) delete root_;
+  if (this != internal_default_instance()) delete last_booted_;
+}
+
+void Hardware::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const Hardware& Hardware::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_Hardware_dmi_2fhw_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void Hardware::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.Hardware)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && last_change_ != nullptr) {
+    delete last_change_;
+  }
+  last_change_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && root_ != nullptr) {
+    delete root_;
+  }
+  root_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && last_booted_ != nullptr) {
+    delete last_booted_;
+  }
+  last_booted_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* Hardware::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<Hardware*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .google.protobuf.Timestamp last_change = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::google::protobuf::Timestamp::_InternalParse;
+        object = msg->mutable_last_change();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.Component root = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Component::_InternalParse;
+        object = msg->mutable_root();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .google.protobuf.Timestamp last_booted = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::google::protobuf::Timestamp::_InternalParse;
+        object = msg->mutable_last_booted();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool Hardware::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.Hardware)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .google.protobuf.Timestamp last_change = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_last_change()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Component root = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_root()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .google.protobuf.Timestamp last_booted = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_last_booted()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.Hardware)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.Hardware)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void Hardware::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.Hardware)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .google.protobuf.Timestamp last_change = 1;
+  if (this->has_last_change()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::last_change(this), output);
+  }
+
+  // .dmi.Component root = 2;
+  if (this->has_root()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::root(this), output);
+  }
+
+  // .google.protobuf.Timestamp last_booted = 3;
+  if (this->has_last_booted()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::last_booted(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.Hardware)
+}
+
+::google::protobuf::uint8* Hardware::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.Hardware)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .google.protobuf.Timestamp last_change = 1;
+  if (this->has_last_change()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::last_change(this), target);
+  }
+
+  // .dmi.Component root = 2;
+  if (this->has_root()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::root(this), target);
+  }
+
+  // .google.protobuf.Timestamp last_booted = 3;
+  if (this->has_last_booted()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::last_booted(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.Hardware)
+  return target;
+}
+
+size_t Hardware::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.Hardware)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .google.protobuf.Timestamp last_change = 1;
+  if (this->has_last_change()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *last_change_);
+  }
+
+  // .dmi.Component root = 2;
+  if (this->has_root()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *root_);
+  }
+
+  // .google.protobuf.Timestamp last_booted = 3;
+  if (this->has_last_booted()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *last_booted_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void Hardware::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.Hardware)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Hardware* source =
+      ::google::protobuf::DynamicCastToGenerated<Hardware>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.Hardware)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.Hardware)
+    MergeFrom(*source);
+  }
+}
+
+void Hardware::MergeFrom(const Hardware& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.Hardware)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_last_change()) {
+    mutable_last_change()->::google::protobuf::Timestamp::MergeFrom(from.last_change());
+  }
+  if (from.has_root()) {
+    mutable_root()->::dmi::Component::MergeFrom(from.root());
+  }
+  if (from.has_last_booted()) {
+    mutable_last_booted()->::google::protobuf::Timestamp::MergeFrom(from.last_booted());
+  }
+}
+
+void Hardware::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.Hardware)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Hardware::CopyFrom(const Hardware& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.Hardware)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Hardware::IsInitialized() const {
+  return true;
+}
+
+void Hardware::Swap(Hardware* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Hardware::InternalSwap(Hardware* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(last_change_, other->last_change_);
+  swap(root_, other->root_);
+  swap(last_booted_, other->last_booted_);
+}
+
+::google::protobuf::Metadata Hardware::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_2eproto);
+  return ::file_level_metadata_dmi_2fhw_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ModifiableComponent::InitAsDefaultInstance() {
+  ::dmi::_ModifiableComponent_default_instance_._instance.get_mutable()->parent_ = const_cast< ::dmi::Component*>(
+      ::dmi::Component::internal_default_instance());
+  ::dmi::_ModifiableComponent_default_instance_._instance.get_mutable()->uri_ = const_cast< ::dmi::Uri*>(
+      ::dmi::Uri::internal_default_instance());
+}
+class ModifiableComponent::HasBitSetters {
+ public:
+  static const ::dmi::Component& parent(const ModifiableComponent* msg);
+  static const ::dmi::Uri& uri(const ModifiableComponent* msg);
+};
+
+const ::dmi::Component&
+ModifiableComponent::HasBitSetters::parent(const ModifiableComponent* msg) {
+  return *msg->parent_;
+}
+const ::dmi::Uri&
+ModifiableComponent::HasBitSetters::uri(const ModifiableComponent* msg) {
+  return *msg->uri_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ModifiableComponent::kNameFieldNumber;
+const int ModifiableComponent::kClassFieldNumber;
+const int ModifiableComponent::kParentFieldNumber;
+const int ModifiableComponent::kParentRelPosFieldNumber;
+const int ModifiableComponent::kAliasFieldNumber;
+const int ModifiableComponent::kAssetIdFieldNumber;
+const int ModifiableComponent::kUriFieldNumber;
+const int ModifiableComponent::kAdminStateFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ModifiableComponent::ModifiableComponent()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ModifiableComponent)
+}
+ModifiableComponent::ModifiableComponent(const ModifiableComponent& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.name().size() > 0) {
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  alias_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.alias().size() > 0) {
+    alias_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.alias_);
+  }
+  asset_id_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.asset_id().size() > 0) {
+    asset_id_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.asset_id_);
+  }
+  if (from.has_parent()) {
+    parent_ = new ::dmi::Component(*from.parent_);
+  } else {
+    parent_ = nullptr;
+  }
+  if (from.has_uri()) {
+    uri_ = new ::dmi::Uri(*from.uri_);
+  } else {
+    uri_ = nullptr;
+  }
+  ::memcpy(&class__, &from.class__,
+    static_cast<size_t>(reinterpret_cast<char*>(&admin_state_) -
+    reinterpret_cast<char*>(&class__)) + sizeof(admin_state_));
+  // @@protoc_insertion_point(copy_constructor:dmi.ModifiableComponent)
+}
+
+void ModifiableComponent::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ModifiableComponent_dmi_2fhw_2eproto.base);
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  alias_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  asset_id_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&parent_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&admin_state_) -
+      reinterpret_cast<char*>(&parent_)) + sizeof(admin_state_));
+}
+
+ModifiableComponent::~ModifiableComponent() {
+  // @@protoc_insertion_point(destructor:dmi.ModifiableComponent)
+  SharedDtor();
+}
+
+void ModifiableComponent::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  alias_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  asset_id_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete parent_;
+  if (this != internal_default_instance()) delete uri_;
+}
+
+void ModifiableComponent::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ModifiableComponent& ModifiableComponent::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ModifiableComponent_dmi_2fhw_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ModifiableComponent::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ModifiableComponent)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  alias_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  asset_id_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && parent_ != nullptr) {
+    delete parent_;
+  }
+  parent_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && uri_ != nullptr) {
+    delete uri_;
+  }
+  uri_ = nullptr;
+  ::memset(&class__, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&admin_state_) -
+      reinterpret_cast<char*>(&class__)) + sizeof(admin_state_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ModifiableComponent::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ModifiableComponent*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // string name = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ModifiableComponent.name");
+        object = msg->mutable_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // .dmi.ComponentType class = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_class_(static_cast<::dmi::ComponentType>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.Component parent = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Component::_InternalParse;
+        object = msg->mutable_parent();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // int32 parent_rel_pos = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 32) goto handle_unusual;
+        msg->set_parent_rel_pos(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string alias = 5;
+      case 5: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ModifiableComponent.alias");
+        object = msg->mutable_alias();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string asset_id = 6;
+      case 6: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 50) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ModifiableComponent.asset_id");
+        object = msg->mutable_asset_id();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // .dmi.Uri uri = 7;
+      case 7: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 58) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uri::_InternalParse;
+        object = msg->mutable_uri();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.ComponentAdminState admin_state = 8;
+      case 8: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 64) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_admin_state(static_cast<::dmi::ComponentAdminState>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ModifiableComponent::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ModifiableComponent)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // string name = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->name().data(), static_cast<int>(this->name().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ModifiableComponent.name"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ComponentType class = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_class_(static_cast< ::dmi::ComponentType >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Component parent = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_parent()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // int32 parent_rel_pos = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (32 & 0xFF)) {
+
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+                 input, &parent_rel_pos_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string alias = 5;
+      case 5: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (42 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_alias()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->alias().data(), static_cast<int>(this->alias().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ModifiableComponent.alias"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string asset_id = 6;
+      case 6: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (50 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_asset_id()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->asset_id().data(), static_cast<int>(this->asset_id().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ModifiableComponent.asset_id"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Uri uri = 7;
+      case 7: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (58 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_uri()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ComponentAdminState admin_state = 8;
+      case 8: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (64 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_admin_state(static_cast< ::dmi::ComponentAdminState >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ModifiableComponent)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ModifiableComponent)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ModifiableComponent::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ModifiableComponent)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), static_cast<int>(this->name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ModifiableComponent.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  // .dmi.ComponentType class = 2;
+  if (this->class_() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->class_(), output);
+  }
+
+  // .dmi.Component parent = 3;
+  if (this->has_parent()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::parent(this), output);
+  }
+
+  // int32 parent_rel_pos = 4;
+  if (this->parent_rel_pos() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt32(4, this->parent_rel_pos(), output);
+  }
+
+  // string alias = 5;
+  if (this->alias().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->alias().data(), static_cast<int>(this->alias().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ModifiableComponent.alias");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      5, this->alias(), output);
+  }
+
+  // string asset_id = 6;
+  if (this->asset_id().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->asset_id().data(), static_cast<int>(this->asset_id().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ModifiableComponent.asset_id");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      6, this->asset_id(), output);
+  }
+
+  // .dmi.Uri uri = 7;
+  if (this->has_uri()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      7, HasBitSetters::uri(this), output);
+  }
+
+  // .dmi.ComponentAdminState admin_state = 8;
+  if (this->admin_state() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      8, this->admin_state(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ModifiableComponent)
+}
+
+::google::protobuf::uint8* ModifiableComponent::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ModifiableComponent)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), static_cast<int>(this->name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ModifiableComponent.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  // .dmi.ComponentType class = 2;
+  if (this->class_() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->class_(), target);
+  }
+
+  // .dmi.Component parent = 3;
+  if (this->has_parent()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::parent(this), target);
+  }
+
+  // int32 parent_rel_pos = 4;
+  if (this->parent_rel_pos() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(4, this->parent_rel_pos(), target);
+  }
+
+  // string alias = 5;
+  if (this->alias().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->alias().data(), static_cast<int>(this->alias().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ModifiableComponent.alias");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        5, this->alias(), target);
+  }
+
+  // string asset_id = 6;
+  if (this->asset_id().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->asset_id().data(), static_cast<int>(this->asset_id().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ModifiableComponent.asset_id");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        6, this->asset_id(), target);
+  }
+
+  // .dmi.Uri uri = 7;
+  if (this->has_uri()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        7, HasBitSetters::uri(this), target);
+  }
+
+  // .dmi.ComponentAdminState admin_state = 8;
+  if (this->admin_state() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      8, this->admin_state(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ModifiableComponent)
+  return target;
+}
+
+size_t ModifiableComponent::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ModifiableComponent)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string name = 1;
+  if (this->name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name());
+  }
+
+  // string alias = 5;
+  if (this->alias().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->alias());
+  }
+
+  // string asset_id = 6;
+  if (this->asset_id().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->asset_id());
+  }
+
+  // .dmi.Component parent = 3;
+  if (this->has_parent()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *parent_);
+  }
+
+  // .dmi.Uri uri = 7;
+  if (this->has_uri()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *uri_);
+  }
+
+  // .dmi.ComponentType class = 2;
+  if (this->class_() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->class_());
+  }
+
+  // int32 parent_rel_pos = 4;
+  if (this->parent_rel_pos() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::Int32Size(
+        this->parent_rel_pos());
+  }
+
+  // .dmi.ComponentAdminState admin_state = 8;
+  if (this->admin_state() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->admin_state());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ModifiableComponent::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ModifiableComponent)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ModifiableComponent* source =
+      ::google::protobuf::DynamicCastToGenerated<ModifiableComponent>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ModifiableComponent)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ModifiableComponent)
+    MergeFrom(*source);
+  }
+}
+
+void ModifiableComponent::MergeFrom(const ModifiableComponent& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ModifiableComponent)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.name().size() > 0) {
+
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  if (from.alias().size() > 0) {
+
+    alias_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.alias_);
+  }
+  if (from.asset_id().size() > 0) {
+
+    asset_id_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.asset_id_);
+  }
+  if (from.has_parent()) {
+    mutable_parent()->::dmi::Component::MergeFrom(from.parent());
+  }
+  if (from.has_uri()) {
+    mutable_uri()->::dmi::Uri::MergeFrom(from.uri());
+  }
+  if (from.class_() != 0) {
+    set_class_(from.class_());
+  }
+  if (from.parent_rel_pos() != 0) {
+    set_parent_rel_pos(from.parent_rel_pos());
+  }
+  if (from.admin_state() != 0) {
+    set_admin_state(from.admin_state());
+  }
+}
+
+void ModifiableComponent::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ModifiableComponent)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ModifiableComponent::CopyFrom(const ModifiableComponent& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ModifiableComponent)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ModifiableComponent::IsInitialized() const {
+  return true;
+}
+
+void ModifiableComponent::Swap(ModifiableComponent* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ModifiableComponent::InternalSwap(ModifiableComponent* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  name_.Swap(&other->name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  alias_.Swap(&other->alias_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  asset_id_.Swap(&other->asset_id_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(parent_, other->parent_);
+  swap(uri_, other->uri_);
+  swap(class__, other->class__);
+  swap(parent_rel_pos_, other->parent_rel_pos_);
+  swap(admin_state_, other->admin_state_);
+}
+
+::google::protobuf::Metadata ModifiableComponent::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_2eproto);
+  return ::file_level_metadata_dmi_2fhw_2eproto[kIndexInFileMessages];
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> PROTOBUF_NOINLINE ::dmi::Uuid* Arena::CreateMaybeMessage< ::dmi::Uuid >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::Uuid >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::HardwareID* Arena::CreateMaybeMessage< ::dmi::HardwareID >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::HardwareID >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::Uri* Arena::CreateMaybeMessage< ::dmi::Uri >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::Uri >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ComponentState* Arena::CreateMaybeMessage< ::dmi::ComponentState >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ComponentState >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ComponentSensorData* Arena::CreateMaybeMessage< ::dmi::ComponentSensorData >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ComponentSensorData >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::PortComponentAttributes* Arena::CreateMaybeMessage< ::dmi::PortComponentAttributes >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::PortComponentAttributes >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ContainerComponentAttributes* Arena::CreateMaybeMessage< ::dmi::ContainerComponentAttributes >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ContainerComponentAttributes >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::PsuComponentAttributes* Arena::CreateMaybeMessage< ::dmi::PsuComponentAttributes >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::PsuComponentAttributes >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::TransceiverComponentsAttributes* Arena::CreateMaybeMessage< ::dmi::TransceiverComponentsAttributes >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::TransceiverComponentsAttributes >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::Component* Arena::CreateMaybeMessage< ::dmi::Component >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::Component >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::Hardware* Arena::CreateMaybeMessage< ::dmi::Hardware >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::Hardware >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ModifiableComponent* Arena::CreateMaybeMessage< ::dmi::ModifiableComponent >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ModifiableComponent >(arena);
+}
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+#include <google/protobuf/port_undef.inc>
diff --git a/cpp/dmi/hw.pb.h b/cpp/dmi/hw.pb.h
new file mode 100644
index 0000000..f4b9c89
--- /dev/null
+++ b/cpp/dmi/hw.pb.h
@@ -0,0 +1,5215 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/hw.proto
+
+#ifndef PROTOBUF_INCLUDED_dmi_2fhw_2eproto
+#define PROTOBUF_INCLUDED_dmi_2fhw_2eproto
+
+#include <limits>
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+#if PROTOBUF_VERSION < 3007000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3007000 < PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/port_undef.inc>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/inlined_string_field.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/timestamp.pb.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+#define PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto
+
+// Internal implementation detail -- do not use these members.
+struct TableStruct_dmi_2fhw_2eproto {
+  static const ::google::protobuf::internal::ParseTableField entries[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::AuxillaryParseTableField aux[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::ParseTable schema[12]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
+  static const ::google::protobuf::uint32 offsets[];
+};
+void AddDescriptors_dmi_2fhw_2eproto();
+namespace dmi {
+class Component;
+class ComponentDefaultTypeInternal;
+extern ComponentDefaultTypeInternal _Component_default_instance_;
+class ComponentSensorData;
+class ComponentSensorDataDefaultTypeInternal;
+extern ComponentSensorDataDefaultTypeInternal _ComponentSensorData_default_instance_;
+class ComponentState;
+class ComponentStateDefaultTypeInternal;
+extern ComponentStateDefaultTypeInternal _ComponentState_default_instance_;
+class ContainerComponentAttributes;
+class ContainerComponentAttributesDefaultTypeInternal;
+extern ContainerComponentAttributesDefaultTypeInternal _ContainerComponentAttributes_default_instance_;
+class Hardware;
+class HardwareDefaultTypeInternal;
+extern HardwareDefaultTypeInternal _Hardware_default_instance_;
+class HardwareID;
+class HardwareIDDefaultTypeInternal;
+extern HardwareIDDefaultTypeInternal _HardwareID_default_instance_;
+class ModifiableComponent;
+class ModifiableComponentDefaultTypeInternal;
+extern ModifiableComponentDefaultTypeInternal _ModifiableComponent_default_instance_;
+class PortComponentAttributes;
+class PortComponentAttributesDefaultTypeInternal;
+extern PortComponentAttributesDefaultTypeInternal _PortComponentAttributes_default_instance_;
+class PsuComponentAttributes;
+class PsuComponentAttributesDefaultTypeInternal;
+extern PsuComponentAttributesDefaultTypeInternal _PsuComponentAttributes_default_instance_;
+class TransceiverComponentsAttributes;
+class TransceiverComponentsAttributesDefaultTypeInternal;
+extern TransceiverComponentsAttributesDefaultTypeInternal _TransceiverComponentsAttributes_default_instance_;
+class Uri;
+class UriDefaultTypeInternal;
+extern UriDefaultTypeInternal _Uri_default_instance_;
+class Uuid;
+class UuidDefaultTypeInternal;
+extern UuidDefaultTypeInternal _Uuid_default_instance_;
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> ::dmi::Component* Arena::CreateMaybeMessage<::dmi::Component>(Arena*);
+template<> ::dmi::ComponentSensorData* Arena::CreateMaybeMessage<::dmi::ComponentSensorData>(Arena*);
+template<> ::dmi::ComponentState* Arena::CreateMaybeMessage<::dmi::ComponentState>(Arena*);
+template<> ::dmi::ContainerComponentAttributes* Arena::CreateMaybeMessage<::dmi::ContainerComponentAttributes>(Arena*);
+template<> ::dmi::Hardware* Arena::CreateMaybeMessage<::dmi::Hardware>(Arena*);
+template<> ::dmi::HardwareID* Arena::CreateMaybeMessage<::dmi::HardwareID>(Arena*);
+template<> ::dmi::ModifiableComponent* Arena::CreateMaybeMessage<::dmi::ModifiableComponent>(Arena*);
+template<> ::dmi::PortComponentAttributes* Arena::CreateMaybeMessage<::dmi::PortComponentAttributes>(Arena*);
+template<> ::dmi::PsuComponentAttributes* Arena::CreateMaybeMessage<::dmi::PsuComponentAttributes>(Arena*);
+template<> ::dmi::TransceiverComponentsAttributes* Arena::CreateMaybeMessage<::dmi::TransceiverComponentsAttributes>(Arena*);
+template<> ::dmi::Uri* Arena::CreateMaybeMessage<::dmi::Uri>(Arena*);
+template<> ::dmi::Uuid* Arena::CreateMaybeMessage<::dmi::Uuid>(Arena*);
+}  // namespace protobuf
+}  // namespace google
+namespace dmi {
+
+enum PortComponentAttributes_ConnectorType {
+  PortComponentAttributes_ConnectorType_CONNECTOR_TYPE_UNDEFINED = 0,
+  PortComponentAttributes_ConnectorType_RJ45 = 1,
+  PortComponentAttributes_ConnectorType_FIBER_LC = 2,
+  PortComponentAttributes_ConnectorType_FIBER_SC_PC = 3,
+  PortComponentAttributes_ConnectorType_FIBER_MPO = 4,
+  PortComponentAttributes_ConnectorType_RS232 = 5,
+  PortComponentAttributes_ConnectorType_PortComponentAttributes_ConnectorType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  PortComponentAttributes_ConnectorType_PortComponentAttributes_ConnectorType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool PortComponentAttributes_ConnectorType_IsValid(int value);
+const PortComponentAttributes_ConnectorType PortComponentAttributes_ConnectorType_ConnectorType_MIN = PortComponentAttributes_ConnectorType_CONNECTOR_TYPE_UNDEFINED;
+const PortComponentAttributes_ConnectorType PortComponentAttributes_ConnectorType_ConnectorType_MAX = PortComponentAttributes_ConnectorType_RS232;
+const int PortComponentAttributes_ConnectorType_ConnectorType_ARRAYSIZE = PortComponentAttributes_ConnectorType_ConnectorType_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* PortComponentAttributes_ConnectorType_descriptor();
+inline const ::std::string& PortComponentAttributes_ConnectorType_Name(PortComponentAttributes_ConnectorType value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    PortComponentAttributes_ConnectorType_descriptor(), value);
+}
+inline bool PortComponentAttributes_ConnectorType_Parse(
+    const ::std::string& name, PortComponentAttributes_ConnectorType* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<PortComponentAttributes_ConnectorType>(
+    PortComponentAttributes_ConnectorType_descriptor(), name, value);
+}
+enum PortComponentAttributes_Speed {
+  PortComponentAttributes_Speed_SPEED_UNDEFINED = 0,
+  PortComponentAttributes_Speed_DYNAMIC = 1,
+  PortComponentAttributes_Speed_GIGABIT_1 = 2,
+  PortComponentAttributes_Speed_GIGABIT_10 = 3,
+  PortComponentAttributes_Speed_GIGABIT_25 = 4,
+  PortComponentAttributes_Speed_GIGABIT_40 = 5,
+  PortComponentAttributes_Speed_GIGABIT_100 = 6,
+  PortComponentAttributes_Speed_GIGABIT_400 = 7,
+  PortComponentAttributes_Speed_MEGABIT_2500 = 8,
+  PortComponentAttributes_Speed_MEGABIT_1250 = 9,
+  PortComponentAttributes_Speed_PortComponentAttributes_Speed_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  PortComponentAttributes_Speed_PortComponentAttributes_Speed_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool PortComponentAttributes_Speed_IsValid(int value);
+const PortComponentAttributes_Speed PortComponentAttributes_Speed_Speed_MIN = PortComponentAttributes_Speed_SPEED_UNDEFINED;
+const PortComponentAttributes_Speed PortComponentAttributes_Speed_Speed_MAX = PortComponentAttributes_Speed_MEGABIT_1250;
+const int PortComponentAttributes_Speed_Speed_ARRAYSIZE = PortComponentAttributes_Speed_Speed_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* PortComponentAttributes_Speed_descriptor();
+inline const ::std::string& PortComponentAttributes_Speed_Name(PortComponentAttributes_Speed value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    PortComponentAttributes_Speed_descriptor(), value);
+}
+inline bool PortComponentAttributes_Speed_Parse(
+    const ::std::string& name, PortComponentAttributes_Speed* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<PortComponentAttributes_Speed>(
+    PortComponentAttributes_Speed_descriptor(), name, value);
+}
+enum PortComponentAttributes_Protocol {
+  PortComponentAttributes_Protocol_PROTOCOL_UNDEFINED = 0,
+  PortComponentAttributes_Protocol_ETHERNET = 1,
+  PortComponentAttributes_Protocol_GPON = 2,
+  PortComponentAttributes_Protocol_XGPON = 3,
+  PortComponentAttributes_Protocol_XGSPON = 4,
+  PortComponentAttributes_Protocol_GFAST = 5,
+  PortComponentAttributes_Protocol_SERIAL = 6,
+  PortComponentAttributes_Protocol_EPON = 7,
+  PortComponentAttributes_Protocol_BITS = 8,
+  PortComponentAttributes_Protocol_PortComponentAttributes_Protocol_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  PortComponentAttributes_Protocol_PortComponentAttributes_Protocol_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool PortComponentAttributes_Protocol_IsValid(int value);
+const PortComponentAttributes_Protocol PortComponentAttributes_Protocol_Protocol_MIN = PortComponentAttributes_Protocol_PROTOCOL_UNDEFINED;
+const PortComponentAttributes_Protocol PortComponentAttributes_Protocol_Protocol_MAX = PortComponentAttributes_Protocol_BITS;
+const int PortComponentAttributes_Protocol_Protocol_ARRAYSIZE = PortComponentAttributes_Protocol_Protocol_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* PortComponentAttributes_Protocol_descriptor();
+inline const ::std::string& PortComponentAttributes_Protocol_Name(PortComponentAttributes_Protocol value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    PortComponentAttributes_Protocol_descriptor(), value);
+}
+inline bool PortComponentAttributes_Protocol_Parse(
+    const ::std::string& name, PortComponentAttributes_Protocol* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<PortComponentAttributes_Protocol>(
+    PortComponentAttributes_Protocol_descriptor(), name, value);
+}
+enum PsuComponentAttributes_SupportedVoltage {
+  PsuComponentAttributes_SupportedVoltage_SUPPORTED_VOLTAGE_UNDEFINED = 0,
+  PsuComponentAttributes_SupportedVoltage_V48 = 1,
+  PsuComponentAttributes_SupportedVoltage_V230 = 2,
+  PsuComponentAttributes_SupportedVoltage_V115 = 3,
+  PsuComponentAttributes_SupportedVoltage_PsuComponentAttributes_SupportedVoltage_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  PsuComponentAttributes_SupportedVoltage_PsuComponentAttributes_SupportedVoltage_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool PsuComponentAttributes_SupportedVoltage_IsValid(int value);
+const PsuComponentAttributes_SupportedVoltage PsuComponentAttributes_SupportedVoltage_SupportedVoltage_MIN = PsuComponentAttributes_SupportedVoltage_SUPPORTED_VOLTAGE_UNDEFINED;
+const PsuComponentAttributes_SupportedVoltage PsuComponentAttributes_SupportedVoltage_SupportedVoltage_MAX = PsuComponentAttributes_SupportedVoltage_V115;
+const int PsuComponentAttributes_SupportedVoltage_SupportedVoltage_ARRAYSIZE = PsuComponentAttributes_SupportedVoltage_SupportedVoltage_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* PsuComponentAttributes_SupportedVoltage_descriptor();
+inline const ::std::string& PsuComponentAttributes_SupportedVoltage_Name(PsuComponentAttributes_SupportedVoltage value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    PsuComponentAttributes_SupportedVoltage_descriptor(), value);
+}
+inline bool PsuComponentAttributes_SupportedVoltage_Parse(
+    const ::std::string& name, PsuComponentAttributes_SupportedVoltage* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<PsuComponentAttributes_SupportedVoltage>(
+    PsuComponentAttributes_SupportedVoltage_descriptor(), name, value);
+}
+enum TransceiverComponentsAttributes_FormFactor {
+  TransceiverComponentsAttributes_FormFactor_FORM_FACTOR_UNKNOWN = 0,
+  TransceiverComponentsAttributes_FormFactor_QSFP = 1,
+  TransceiverComponentsAttributes_FormFactor_QSFP_PLUS = 2,
+  TransceiverComponentsAttributes_FormFactor_QSFP28 = 3,
+  TransceiverComponentsAttributes_FormFactor_SFP = 4,
+  TransceiverComponentsAttributes_FormFactor_SFP_PLUS = 5,
+  TransceiverComponentsAttributes_FormFactor_XFP = 6,
+  TransceiverComponentsAttributes_FormFactor_CFP4 = 7,
+  TransceiverComponentsAttributes_FormFactor_CFP2 = 8,
+  TransceiverComponentsAttributes_FormFactor_CPAK = 9,
+  TransceiverComponentsAttributes_FormFactor_X2 = 10,
+  TransceiverComponentsAttributes_FormFactor_OTHER = 11,
+  TransceiverComponentsAttributes_FormFactor_CFP = 12,
+  TransceiverComponentsAttributes_FormFactor_CFP2_ACO = 13,
+  TransceiverComponentsAttributes_FormFactor_CFP2_DCO = 14,
+  TransceiverComponentsAttributes_FormFactor_TransceiverComponentsAttributes_FormFactor_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  TransceiverComponentsAttributes_FormFactor_TransceiverComponentsAttributes_FormFactor_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool TransceiverComponentsAttributes_FormFactor_IsValid(int value);
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes_FormFactor_FormFactor_MIN = TransceiverComponentsAttributes_FormFactor_FORM_FACTOR_UNKNOWN;
+const TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes_FormFactor_FormFactor_MAX = TransceiverComponentsAttributes_FormFactor_CFP2_DCO;
+const int TransceiverComponentsAttributes_FormFactor_FormFactor_ARRAYSIZE = TransceiverComponentsAttributes_FormFactor_FormFactor_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* TransceiverComponentsAttributes_FormFactor_descriptor();
+inline const ::std::string& TransceiverComponentsAttributes_FormFactor_Name(TransceiverComponentsAttributes_FormFactor value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    TransceiverComponentsAttributes_FormFactor_descriptor(), value);
+}
+inline bool TransceiverComponentsAttributes_FormFactor_Parse(
+    const ::std::string& name, TransceiverComponentsAttributes_FormFactor* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<TransceiverComponentsAttributes_FormFactor>(
+    TransceiverComponentsAttributes_FormFactor_descriptor(), name, value);
+}
+enum TransceiverComponentsAttributes_Type {
+  TransceiverComponentsAttributes_Type_TYPE_UNKNOWN = 0,
+  TransceiverComponentsAttributes_Type_ETHERNET = 1,
+  TransceiverComponentsAttributes_Type_GPON = 2,
+  TransceiverComponentsAttributes_Type_XGPON = 3,
+  TransceiverComponentsAttributes_Type_XGSPON = 4,
+  TransceiverComponentsAttributes_Type_CPON = 5,
+  TransceiverComponentsAttributes_Type_NG_PON2 = 6,
+  TransceiverComponentsAttributes_Type_EPON = 7,
+  TransceiverComponentsAttributes_Type_TransceiverComponentsAttributes_Type_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  TransceiverComponentsAttributes_Type_TransceiverComponentsAttributes_Type_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool TransceiverComponentsAttributes_Type_IsValid(int value);
+const TransceiverComponentsAttributes_Type TransceiverComponentsAttributes_Type_Type_MIN = TransceiverComponentsAttributes_Type_TYPE_UNKNOWN;
+const TransceiverComponentsAttributes_Type TransceiverComponentsAttributes_Type_Type_MAX = TransceiverComponentsAttributes_Type_EPON;
+const int TransceiverComponentsAttributes_Type_Type_ARRAYSIZE = TransceiverComponentsAttributes_Type_Type_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* TransceiverComponentsAttributes_Type_descriptor();
+inline const ::std::string& TransceiverComponentsAttributes_Type_Name(TransceiverComponentsAttributes_Type value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    TransceiverComponentsAttributes_Type_descriptor(), value);
+}
+inline bool TransceiverComponentsAttributes_Type_Parse(
+    const ::std::string& name, TransceiverComponentsAttributes_Type* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<TransceiverComponentsAttributes_Type>(
+    TransceiverComponentsAttributes_Type_descriptor(), name, value);
+}
+enum ComponentType {
+  COMPONENT_TYPE_UNDEFINED = 0,
+  COMPONENT_TYPE_UNKNOWN = 1,
+  COMPONENT_TYPE_CHASSIS = 2,
+  COMPONENT_TYPE_BACKPLANE = 3,
+  COMPONENT_TYPE_CONTAINER = 4,
+  COMPONENT_TYPE_POWER_SUPPLY = 5,
+  COMPONENT_TYPE_FAN = 6,
+  COMPONENT_TYPE_SENSOR = 7,
+  COMPONENT_TYPE_MODULE = 8,
+  COMPONENT_TYPE_PORT = 9,
+  COMPONENT_TYPE_CPU = 10,
+  COMPONENT_TYPE_BATTERY = 11,
+  COMPONENT_TYPE_STORAGE = 12,
+  COMPONENT_TYPE_MEMORY = 13,
+  COMPONENT_TYPE_TRANSCEIVER = 14,
+  ComponentType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ComponentType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ComponentType_IsValid(int value);
+const ComponentType ComponentType_MIN = COMPONENT_TYPE_UNDEFINED;
+const ComponentType ComponentType_MAX = COMPONENT_TYPE_TRANSCEIVER;
+const int ComponentType_ARRAYSIZE = ComponentType_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ComponentType_descriptor();
+inline const ::std::string& ComponentType_Name(ComponentType value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ComponentType_descriptor(), value);
+}
+inline bool ComponentType_Parse(
+    const ::std::string& name, ComponentType* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ComponentType>(
+    ComponentType_descriptor(), name, value);
+}
+enum ComponentAdminState {
+  COMP_ADMIN_STATE_UNDEFINED = 0,
+  COMP_ADMIN_STATE_UNKNOWN = 1,
+  COMP_ADMIN_STATE_LOCKED = 2,
+  COMP_ADMIN_STATE_SHUTTING_DOWN = 3,
+  COMP_ADMIN_STATE_UNLOCKED = 4,
+  ComponentAdminState_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ComponentAdminState_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ComponentAdminState_IsValid(int value);
+const ComponentAdminState ComponentAdminState_MIN = COMP_ADMIN_STATE_UNDEFINED;
+const ComponentAdminState ComponentAdminState_MAX = COMP_ADMIN_STATE_UNLOCKED;
+const int ComponentAdminState_ARRAYSIZE = ComponentAdminState_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ComponentAdminState_descriptor();
+inline const ::std::string& ComponentAdminState_Name(ComponentAdminState value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ComponentAdminState_descriptor(), value);
+}
+inline bool ComponentAdminState_Parse(
+    const ::std::string& name, ComponentAdminState* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ComponentAdminState>(
+    ComponentAdminState_descriptor(), name, value);
+}
+enum ComponentOperState {
+  COMP_OPER_STATE_UNDEFINED = 0,
+  COMP_OPER_STATE_UNKNOWN = 1,
+  COMP_OPER_STATE_DISABLED = 2,
+  COMP_OPER_STATE_ENABLED = 3,
+  COMP_OPER_STATE_TESTING = 4,
+  ComponentOperState_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ComponentOperState_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ComponentOperState_IsValid(int value);
+const ComponentOperState ComponentOperState_MIN = COMP_OPER_STATE_UNDEFINED;
+const ComponentOperState ComponentOperState_MAX = COMP_OPER_STATE_TESTING;
+const int ComponentOperState_ARRAYSIZE = ComponentOperState_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ComponentOperState_descriptor();
+inline const ::std::string& ComponentOperState_Name(ComponentOperState value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ComponentOperState_descriptor(), value);
+}
+inline bool ComponentOperState_Parse(
+    const ::std::string& name, ComponentOperState* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ComponentOperState>(
+    ComponentOperState_descriptor(), name, value);
+}
+enum ComponentUsageState {
+  COMP_USAGE_STATE_UNDEFINED = 0,
+  COMP_USAGE_STATE_UNKNOWN = 1,
+  COMP_USAGE_STATE_IDLE = 2,
+  COMP_USAGE_STATE_ACTIVE = 3,
+  COMP_USAGE_STATE_BUSY = 4,
+  ComponentUsageState_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ComponentUsageState_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ComponentUsageState_IsValid(int value);
+const ComponentUsageState ComponentUsageState_MIN = COMP_USAGE_STATE_UNDEFINED;
+const ComponentUsageState ComponentUsageState_MAX = COMP_USAGE_STATE_BUSY;
+const int ComponentUsageState_ARRAYSIZE = ComponentUsageState_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ComponentUsageState_descriptor();
+inline const ::std::string& ComponentUsageState_Name(ComponentUsageState value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ComponentUsageState_descriptor(), value);
+}
+inline bool ComponentUsageState_Parse(
+    const ::std::string& name, ComponentUsageState* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ComponentUsageState>(
+    ComponentUsageState_descriptor(), name, value);
+}
+enum ComponentAlarmState {
+  COMP_ALARM_STATE_UNDEFINED = 0,
+  COMP_ALARM_STATE_UNKNOWN = 1,
+  COMP_ALARM_STATE_UNDER_REPAIR = 2,
+  COMP_ALARM_STATE_CRITICAL = 3,
+  COMP_ALARM_STATE_MAJOR = 4,
+  COMP_ALARM_STATE_MINOR = 5,
+  COMP_ALARM_STATE_WARNING = 6,
+  COMP_ALARM_STATE_INDETERMINATE = 7,
+  ComponentAlarmState_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ComponentAlarmState_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ComponentAlarmState_IsValid(int value);
+const ComponentAlarmState ComponentAlarmState_MIN = COMP_ALARM_STATE_UNDEFINED;
+const ComponentAlarmState ComponentAlarmState_MAX = COMP_ALARM_STATE_INDETERMINATE;
+const int ComponentAlarmState_ARRAYSIZE = ComponentAlarmState_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ComponentAlarmState_descriptor();
+inline const ::std::string& ComponentAlarmState_Name(ComponentAlarmState value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ComponentAlarmState_descriptor(), value);
+}
+inline bool ComponentAlarmState_Parse(
+    const ::std::string& name, ComponentAlarmState* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ComponentAlarmState>(
+    ComponentAlarmState_descriptor(), name, value);
+}
+enum ComponentStandbyState {
+  COMP_STANDBY_STATE_UNDEFINED = 0,
+  COMP_STANDBY_STATE_UNKNOWN = 1,
+  COMP_STANDBY_STATE_HOT = 2,
+  COMP_STANDBY_STATE_COLD = 3,
+  COMP_STANDBY_STATE_PROVIDING_SERVICE = 4,
+  ComponentStandbyState_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ComponentStandbyState_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ComponentStandbyState_IsValid(int value);
+const ComponentStandbyState ComponentStandbyState_MIN = COMP_STANDBY_STATE_UNDEFINED;
+const ComponentStandbyState ComponentStandbyState_MAX = COMP_STANDBY_STATE_PROVIDING_SERVICE;
+const int ComponentStandbyState_ARRAYSIZE = ComponentStandbyState_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ComponentStandbyState_descriptor();
+inline const ::std::string& ComponentStandbyState_Name(ComponentStandbyState value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ComponentStandbyState_descriptor(), value);
+}
+inline bool ComponentStandbyState_Parse(
+    const ::std::string& name, ComponentStandbyState* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ComponentStandbyState>(
+    ComponentStandbyState_descriptor(), name, value);
+}
+enum DataValueType {
+  VALUE_TYPE_UNDEFINED = 0,
+  VALUE_TYPE_OTHER = 1,
+  VALUE_TYPE_UNKNOWN = 2,
+  VALUE_TYPE_VOLTS_AC = 3,
+  VALUE_TYPE_VOLTS_DC = 4,
+  VALUE_TYPE_AMPERES = 5,
+  VALUE_TYPE_WATTS = 6,
+  VALUE_TYPE_HERTZ = 7,
+  VALUE_TYPE_CELSIUS = 8,
+  VALUE_TYPE_PERCENT_RH = 9,
+  VALUE_TYPE_RPM = 10,
+  VALUE_TYPE_CMM = 11,
+  VALUE_TYPE_TRUTH_VALUE = 12,
+  VALUE_TYPE_PERCENT = 13,
+  VALUE_TYPE_METERS = 14,
+  VALUE_TYPE_BYTES = 15,
+  DataValueType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  DataValueType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool DataValueType_IsValid(int value);
+const DataValueType DataValueType_MIN = VALUE_TYPE_UNDEFINED;
+const DataValueType DataValueType_MAX = VALUE_TYPE_BYTES;
+const int DataValueType_ARRAYSIZE = DataValueType_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* DataValueType_descriptor();
+inline const ::std::string& DataValueType_Name(DataValueType value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    DataValueType_descriptor(), value);
+}
+inline bool DataValueType_Parse(
+    const ::std::string& name, DataValueType* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<DataValueType>(
+    DataValueType_descriptor(), name, value);
+}
+enum ValueScale {
+  VALUE_SCALE_UNDEFINED = 0,
+  VALUE_SCALE_YOCTO = 1,
+  VALUE_SCALE_ZEPTO = 2,
+  VALUE_SCALE_ATTO = 3,
+  VALUE_SCALE_FEMTO = 4,
+  VALUE_SCALE_PICO = 5,
+  VALUE_SCALE_NANO = 6,
+  VALUE_SCALE_MICRO = 7,
+  VALUE_SCALE_MILLI = 8,
+  VALUE_SCALE_UNITS = 9,
+  VALUE_SCALE_KILO = 10,
+  VALUE_SCALE_MEGA = 11,
+  VALUE_SCALE_GIGA = 12,
+  VALUE_SCALE_TERA = 13,
+  VALUE_SCALE_PETA = 14,
+  VALUE_SCALE_EXA = 15,
+  VALUE_SCALE_ZETTA = 16,
+  VALUE_SCALE_YOTTA = 17,
+  ValueScale_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ValueScale_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ValueScale_IsValid(int value);
+const ValueScale ValueScale_MIN = VALUE_SCALE_UNDEFINED;
+const ValueScale ValueScale_MAX = VALUE_SCALE_YOTTA;
+const int ValueScale_ARRAYSIZE = ValueScale_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ValueScale_descriptor();
+inline const ::std::string& ValueScale_Name(ValueScale value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ValueScale_descriptor(), value);
+}
+inline bool ValueScale_Parse(
+    const ::std::string& name, ValueScale* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ValueScale>(
+    ValueScale_descriptor(), name, value);
+}
+enum SensorStatus {
+  SENSOR_STATUS_UNDEFINED = 0,
+  SENSOR_STATUS_OK = 1,
+  SENSOR_STATUS_UNAVAILABLE = 2,
+  SENSOR_STATUS_NONOPERATIONAL = 3,
+  SensorStatus_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  SensorStatus_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool SensorStatus_IsValid(int value);
+const SensorStatus SensorStatus_MIN = SENSOR_STATUS_UNDEFINED;
+const SensorStatus SensorStatus_MAX = SENSOR_STATUS_NONOPERATIONAL;
+const int SensorStatus_ARRAYSIZE = SensorStatus_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* SensorStatus_descriptor();
+inline const ::std::string& SensorStatus_Name(SensorStatus value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    SensorStatus_descriptor(), value);
+}
+inline bool SensorStatus_Parse(
+    const ::std::string& name, SensorStatus* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<SensorStatus>(
+    SensorStatus_descriptor(), name, value);
+}
+// ===================================================================
+
+class Uuid final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.Uuid) */ {
+ public:
+  Uuid();
+  virtual ~Uuid();
+
+  Uuid(const Uuid& from);
+
+  inline Uuid& operator=(const Uuid& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Uuid(Uuid&& from) noexcept
+    : Uuid() {
+    *this = ::std::move(from);
+  }
+
+  inline Uuid& operator=(Uuid&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const Uuid& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Uuid* internal_default_instance() {
+    return reinterpret_cast<const Uuid*>(
+               &_Uuid_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    0;
+
+  void Swap(Uuid* other);
+  friend void swap(Uuid& a, Uuid& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Uuid* New() const final {
+    return CreateMaybeMessage<Uuid>(nullptr);
+  }
+
+  Uuid* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<Uuid>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const Uuid& from);
+  void MergeFrom(const Uuid& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Uuid* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string uuid = 1;
+  void clear_uuid();
+  static const int kUuidFieldNumber = 1;
+  const ::std::string& uuid() const;
+  void set_uuid(const ::std::string& value);
+  #if LANG_CXX11
+  void set_uuid(::std::string&& value);
+  #endif
+  void set_uuid(const char* value);
+  void set_uuid(const char* value, size_t size);
+  ::std::string* mutable_uuid();
+  ::std::string* release_uuid();
+  void set_allocated_uuid(::std::string* uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.Uuid)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_2eproto;
+};
+// -------------------------------------------------------------------
+
+class HardwareID final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.HardwareID) */ {
+ public:
+  HardwareID();
+  virtual ~HardwareID();
+
+  HardwareID(const HardwareID& from);
+
+  inline HardwareID& operator=(const HardwareID& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  HardwareID(HardwareID&& from) noexcept
+    : HardwareID() {
+    *this = ::std::move(from);
+  }
+
+  inline HardwareID& operator=(HardwareID&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const HardwareID& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const HardwareID* internal_default_instance() {
+    return reinterpret_cast<const HardwareID*>(
+               &_HardwareID_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    1;
+
+  void Swap(HardwareID* other);
+  friend void swap(HardwareID& a, HardwareID& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline HardwareID* New() const final {
+    return CreateMaybeMessage<HardwareID>(nullptr);
+  }
+
+  HardwareID* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<HardwareID>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const HardwareID& from);
+  void MergeFrom(const HardwareID& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(HardwareID* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.Uuid uuid = 1;
+  bool has_uuid() const;
+  void clear_uuid();
+  static const int kUuidFieldNumber = 1;
+  const ::dmi::Uuid& uuid() const;
+  ::dmi::Uuid* release_uuid();
+  ::dmi::Uuid* mutable_uuid();
+  void set_allocated_uuid(::dmi::Uuid* uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.HardwareID)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::Uuid* uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_2eproto;
+};
+// -------------------------------------------------------------------
+
+class Uri final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.Uri) */ {
+ public:
+  Uri();
+  virtual ~Uri();
+
+  Uri(const Uri& from);
+
+  inline Uri& operator=(const Uri& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Uri(Uri&& from) noexcept
+    : Uri() {
+    *this = ::std::move(from);
+  }
+
+  inline Uri& operator=(Uri&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const Uri& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Uri* internal_default_instance() {
+    return reinterpret_cast<const Uri*>(
+               &_Uri_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    2;
+
+  void Swap(Uri* other);
+  friend void swap(Uri& a, Uri& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Uri* New() const final {
+    return CreateMaybeMessage<Uri>(nullptr);
+  }
+
+  Uri* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<Uri>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const Uri& from);
+  void MergeFrom(const Uri& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Uri* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string uri = 1;
+  void clear_uri();
+  static const int kUriFieldNumber = 1;
+  const ::std::string& uri() const;
+  void set_uri(const ::std::string& value);
+  #if LANG_CXX11
+  void set_uri(::std::string&& value);
+  #endif
+  void set_uri(const char* value);
+  void set_uri(const char* value, size_t size);
+  ::std::string* mutable_uri();
+  ::std::string* release_uri();
+  void set_allocated_uri(::std::string* uri);
+
+  // @@protoc_insertion_point(class_scope:dmi.Uri)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr uri_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ComponentState final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ComponentState) */ {
+ public:
+  ComponentState();
+  virtual ~ComponentState();
+
+  ComponentState(const ComponentState& from);
+
+  inline ComponentState& operator=(const ComponentState& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ComponentState(ComponentState&& from) noexcept
+    : ComponentState() {
+    *this = ::std::move(from);
+  }
+
+  inline ComponentState& operator=(ComponentState&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ComponentState& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ComponentState* internal_default_instance() {
+    return reinterpret_cast<const ComponentState*>(
+               &_ComponentState_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    3;
+
+  void Swap(ComponentState* other);
+  friend void swap(ComponentState& a, ComponentState& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ComponentState* New() const final {
+    return CreateMaybeMessage<ComponentState>(nullptr);
+  }
+
+  ComponentState* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ComponentState>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ComponentState& from);
+  void MergeFrom(const ComponentState& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ComponentState* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .google.protobuf.Timestamp state_last_changed = 1;
+  bool has_state_last_changed() const;
+  void clear_state_last_changed();
+  static const int kStateLastChangedFieldNumber = 1;
+  const ::google::protobuf::Timestamp& state_last_changed() const;
+  ::google::protobuf::Timestamp* release_state_last_changed();
+  ::google::protobuf::Timestamp* mutable_state_last_changed();
+  void set_allocated_state_last_changed(::google::protobuf::Timestamp* state_last_changed);
+
+  // .dmi.ComponentAdminState admin_state = 2;
+  void clear_admin_state();
+  static const int kAdminStateFieldNumber = 2;
+  ::dmi::ComponentAdminState admin_state() const;
+  void set_admin_state(::dmi::ComponentAdminState value);
+
+  // .dmi.ComponentOperState oper_state = 3;
+  void clear_oper_state();
+  static const int kOperStateFieldNumber = 3;
+  ::dmi::ComponentOperState oper_state() const;
+  void set_oper_state(::dmi::ComponentOperState value);
+
+  // .dmi.ComponentUsageState usage_state = 4;
+  void clear_usage_state();
+  static const int kUsageStateFieldNumber = 4;
+  ::dmi::ComponentUsageState usage_state() const;
+  void set_usage_state(::dmi::ComponentUsageState value);
+
+  // .dmi.ComponentAlarmState alarm_state = 5;
+  void clear_alarm_state();
+  static const int kAlarmStateFieldNumber = 5;
+  ::dmi::ComponentAlarmState alarm_state() const;
+  void set_alarm_state(::dmi::ComponentAlarmState value);
+
+  // .dmi.ComponentStandbyState standby_state = 6;
+  void clear_standby_state();
+  static const int kStandbyStateFieldNumber = 6;
+  ::dmi::ComponentStandbyState standby_state() const;
+  void set_standby_state(::dmi::ComponentStandbyState value);
+
+  // @@protoc_insertion_point(class_scope:dmi.ComponentState)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::Timestamp* state_last_changed_;
+  int admin_state_;
+  int oper_state_;
+  int usage_state_;
+  int alarm_state_;
+  int standby_state_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ComponentSensorData final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ComponentSensorData) */ {
+ public:
+  ComponentSensorData();
+  virtual ~ComponentSensorData();
+
+  ComponentSensorData(const ComponentSensorData& from);
+
+  inline ComponentSensorData& operator=(const ComponentSensorData& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ComponentSensorData(ComponentSensorData&& from) noexcept
+    : ComponentSensorData() {
+    *this = ::std::move(from);
+  }
+
+  inline ComponentSensorData& operator=(ComponentSensorData&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ComponentSensorData& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ComponentSensorData* internal_default_instance() {
+    return reinterpret_cast<const ComponentSensorData*>(
+               &_ComponentSensorData_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    4;
+
+  void Swap(ComponentSensorData* other);
+  friend void swap(ComponentSensorData& a, ComponentSensorData& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ComponentSensorData* New() const final {
+    return CreateMaybeMessage<ComponentSensorData>(nullptr);
+  }
+
+  ComponentSensorData* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ComponentSensorData>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ComponentSensorData& from);
+  void MergeFrom(const ComponentSensorData& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ComponentSensorData* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string units_display = 6;
+  void clear_units_display();
+  static const int kUnitsDisplayFieldNumber = 6;
+  const ::std::string& units_display() const;
+  void set_units_display(const ::std::string& value);
+  #if LANG_CXX11
+  void set_units_display(::std::string&& value);
+  #endif
+  void set_units_display(const char* value);
+  void set_units_display(const char* value, size_t size);
+  ::std::string* mutable_units_display();
+  ::std::string* release_units_display();
+  void set_allocated_units_display(::std::string* units_display);
+
+  // string data_type = 9;
+  void clear_data_type();
+  static const int kDataTypeFieldNumber = 9;
+  const ::std::string& data_type() const;
+  void set_data_type(const ::std::string& value);
+  #if LANG_CXX11
+  void set_data_type(::std::string&& value);
+  #endif
+  void set_data_type(const char* value);
+  void set_data_type(const char* value, size_t size);
+  ::std::string* mutable_data_type();
+  ::std::string* release_data_type();
+  void set_allocated_data_type(::std::string* data_type);
+
+  // .google.protobuf.Timestamp timestamp = 7;
+  bool has_timestamp() const;
+  void clear_timestamp();
+  static const int kTimestampFieldNumber = 7;
+  const ::google::protobuf::Timestamp& timestamp() const;
+  ::google::protobuf::Timestamp* release_timestamp();
+  ::google::protobuf::Timestamp* mutable_timestamp();
+  void set_allocated_timestamp(::google::protobuf::Timestamp* timestamp);
+
+  // int32 value = 1;
+  void clear_value();
+  static const int kValueFieldNumber = 1;
+  ::google::protobuf::int32 value() const;
+  void set_value(::google::protobuf::int32 value);
+
+  // .dmi.DataValueType type = 2;
+  void clear_type();
+  static const int kTypeFieldNumber = 2;
+  ::dmi::DataValueType type() const;
+  void set_type(::dmi::DataValueType value);
+
+  // .dmi.ValueScale scale = 3;
+  void clear_scale();
+  static const int kScaleFieldNumber = 3;
+  ::dmi::ValueScale scale() const;
+  void set_scale(::dmi::ValueScale value);
+
+  // int32 precision = 4;
+  void clear_precision();
+  static const int kPrecisionFieldNumber = 4;
+  ::google::protobuf::int32 precision() const;
+  void set_precision(::google::protobuf::int32 value);
+
+  // .dmi.SensorStatus status = 5;
+  void clear_status();
+  static const int kStatusFieldNumber = 5;
+  ::dmi::SensorStatus status() const;
+  void set_status(::dmi::SensorStatus value);
+
+  // uint32 value_update_rate = 8;
+  void clear_value_update_rate();
+  static const int kValueUpdateRateFieldNumber = 8;
+  ::google::protobuf::uint32 value_update_rate() const;
+  void set_value_update_rate(::google::protobuf::uint32 value);
+
+  // @@protoc_insertion_point(class_scope:dmi.ComponentSensorData)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr units_display_;
+  ::google::protobuf::internal::ArenaStringPtr data_type_;
+  ::google::protobuf::Timestamp* timestamp_;
+  ::google::protobuf::int32 value_;
+  int type_;
+  int scale_;
+  ::google::protobuf::int32 precision_;
+  int status_;
+  ::google::protobuf::uint32 value_update_rate_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_2eproto;
+};
+// -------------------------------------------------------------------
+
+class PortComponentAttributes final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.PortComponentAttributes) */ {
+ public:
+  PortComponentAttributes();
+  virtual ~PortComponentAttributes();
+
+  PortComponentAttributes(const PortComponentAttributes& from);
+
+  inline PortComponentAttributes& operator=(const PortComponentAttributes& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  PortComponentAttributes(PortComponentAttributes&& from) noexcept
+    : PortComponentAttributes() {
+    *this = ::std::move(from);
+  }
+
+  inline PortComponentAttributes& operator=(PortComponentAttributes&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const PortComponentAttributes& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const PortComponentAttributes* internal_default_instance() {
+    return reinterpret_cast<const PortComponentAttributes*>(
+               &_PortComponentAttributes_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    5;
+
+  void Swap(PortComponentAttributes* other);
+  friend void swap(PortComponentAttributes& a, PortComponentAttributes& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline PortComponentAttributes* New() const final {
+    return CreateMaybeMessage<PortComponentAttributes>(nullptr);
+  }
+
+  PortComponentAttributes* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<PortComponentAttributes>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const PortComponentAttributes& from);
+  void MergeFrom(const PortComponentAttributes& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(PortComponentAttributes* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef PortComponentAttributes_ConnectorType ConnectorType;
+  static const ConnectorType CONNECTOR_TYPE_UNDEFINED =
+    PortComponentAttributes_ConnectorType_CONNECTOR_TYPE_UNDEFINED;
+  static const ConnectorType RJ45 =
+    PortComponentAttributes_ConnectorType_RJ45;
+  static const ConnectorType FIBER_LC =
+    PortComponentAttributes_ConnectorType_FIBER_LC;
+  static const ConnectorType FIBER_SC_PC =
+    PortComponentAttributes_ConnectorType_FIBER_SC_PC;
+  static const ConnectorType FIBER_MPO =
+    PortComponentAttributes_ConnectorType_FIBER_MPO;
+  static const ConnectorType RS232 =
+    PortComponentAttributes_ConnectorType_RS232;
+  static inline bool ConnectorType_IsValid(int value) {
+    return PortComponentAttributes_ConnectorType_IsValid(value);
+  }
+  static const ConnectorType ConnectorType_MIN =
+    PortComponentAttributes_ConnectorType_ConnectorType_MIN;
+  static const ConnectorType ConnectorType_MAX =
+    PortComponentAttributes_ConnectorType_ConnectorType_MAX;
+  static const int ConnectorType_ARRAYSIZE =
+    PortComponentAttributes_ConnectorType_ConnectorType_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  ConnectorType_descriptor() {
+    return PortComponentAttributes_ConnectorType_descriptor();
+  }
+  static inline const ::std::string& ConnectorType_Name(ConnectorType value) {
+    return PortComponentAttributes_ConnectorType_Name(value);
+  }
+  static inline bool ConnectorType_Parse(const ::std::string& name,
+      ConnectorType* value) {
+    return PortComponentAttributes_ConnectorType_Parse(name, value);
+  }
+
+  typedef PortComponentAttributes_Speed Speed;
+  static const Speed SPEED_UNDEFINED =
+    PortComponentAttributes_Speed_SPEED_UNDEFINED;
+  static const Speed DYNAMIC =
+    PortComponentAttributes_Speed_DYNAMIC;
+  static const Speed GIGABIT_1 =
+    PortComponentAttributes_Speed_GIGABIT_1;
+  static const Speed GIGABIT_10 =
+    PortComponentAttributes_Speed_GIGABIT_10;
+  static const Speed GIGABIT_25 =
+    PortComponentAttributes_Speed_GIGABIT_25;
+  static const Speed GIGABIT_40 =
+    PortComponentAttributes_Speed_GIGABIT_40;
+  static const Speed GIGABIT_100 =
+    PortComponentAttributes_Speed_GIGABIT_100;
+  static const Speed GIGABIT_400 =
+    PortComponentAttributes_Speed_GIGABIT_400;
+  static const Speed MEGABIT_2500 =
+    PortComponentAttributes_Speed_MEGABIT_2500;
+  static const Speed MEGABIT_1250 =
+    PortComponentAttributes_Speed_MEGABIT_1250;
+  static inline bool Speed_IsValid(int value) {
+    return PortComponentAttributes_Speed_IsValid(value);
+  }
+  static const Speed Speed_MIN =
+    PortComponentAttributes_Speed_Speed_MIN;
+  static const Speed Speed_MAX =
+    PortComponentAttributes_Speed_Speed_MAX;
+  static const int Speed_ARRAYSIZE =
+    PortComponentAttributes_Speed_Speed_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Speed_descriptor() {
+    return PortComponentAttributes_Speed_descriptor();
+  }
+  static inline const ::std::string& Speed_Name(Speed value) {
+    return PortComponentAttributes_Speed_Name(value);
+  }
+  static inline bool Speed_Parse(const ::std::string& name,
+      Speed* value) {
+    return PortComponentAttributes_Speed_Parse(name, value);
+  }
+
+  typedef PortComponentAttributes_Protocol Protocol;
+  static const Protocol PROTOCOL_UNDEFINED =
+    PortComponentAttributes_Protocol_PROTOCOL_UNDEFINED;
+  static const Protocol ETHERNET =
+    PortComponentAttributes_Protocol_ETHERNET;
+  static const Protocol GPON =
+    PortComponentAttributes_Protocol_GPON;
+  static const Protocol XGPON =
+    PortComponentAttributes_Protocol_XGPON;
+  static const Protocol XGSPON =
+    PortComponentAttributes_Protocol_XGSPON;
+  static const Protocol GFAST =
+    PortComponentAttributes_Protocol_GFAST;
+  static const Protocol SERIAL =
+    PortComponentAttributes_Protocol_SERIAL;
+  static const Protocol EPON =
+    PortComponentAttributes_Protocol_EPON;
+  static const Protocol BITS =
+    PortComponentAttributes_Protocol_BITS;
+  static inline bool Protocol_IsValid(int value) {
+    return PortComponentAttributes_Protocol_IsValid(value);
+  }
+  static const Protocol Protocol_MIN =
+    PortComponentAttributes_Protocol_Protocol_MIN;
+  static const Protocol Protocol_MAX =
+    PortComponentAttributes_Protocol_Protocol_MAX;
+  static const int Protocol_ARRAYSIZE =
+    PortComponentAttributes_Protocol_Protocol_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Protocol_descriptor() {
+    return PortComponentAttributes_Protocol_descriptor();
+  }
+  static inline const ::std::string& Protocol_Name(Protocol value) {
+    return PortComponentAttributes_Protocol_Name(value);
+  }
+  static inline bool Protocol_Parse(const ::std::string& name,
+      Protocol* value) {
+    return PortComponentAttributes_Protocol_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string physical_label = 4;
+  void clear_physical_label();
+  static const int kPhysicalLabelFieldNumber = 4;
+  const ::std::string& physical_label() const;
+  void set_physical_label(const ::std::string& value);
+  #if LANG_CXX11
+  void set_physical_label(::std::string&& value);
+  #endif
+  void set_physical_label(const char* value);
+  void set_physical_label(const char* value, size_t size);
+  ::std::string* mutable_physical_label();
+  ::std::string* release_physical_label();
+  void set_allocated_physical_label(::std::string* physical_label);
+
+  // .dmi.PortComponentAttributes.ConnectorType connector_type = 1;
+  void clear_connector_type();
+  static const int kConnectorTypeFieldNumber = 1;
+  ::dmi::PortComponentAttributes_ConnectorType connector_type() const;
+  void set_connector_type(::dmi::PortComponentAttributes_ConnectorType value);
+
+  // .dmi.PortComponentAttributes.Speed speed = 2;
+  void clear_speed();
+  static const int kSpeedFieldNumber = 2;
+  ::dmi::PortComponentAttributes_Speed speed() const;
+  void set_speed(::dmi::PortComponentAttributes_Speed value);
+
+  // .dmi.PortComponentAttributes.Protocol protocol = 3;
+  void clear_protocol();
+  static const int kProtocolFieldNumber = 3;
+  ::dmi::PortComponentAttributes_Protocol protocol() const;
+  void set_protocol(::dmi::PortComponentAttributes_Protocol value);
+
+  // @@protoc_insertion_point(class_scope:dmi.PortComponentAttributes)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr physical_label_;
+  int connector_type_;
+  int speed_;
+  int protocol_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ContainerComponentAttributes final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ContainerComponentAttributes) */ {
+ public:
+  ContainerComponentAttributes();
+  virtual ~ContainerComponentAttributes();
+
+  ContainerComponentAttributes(const ContainerComponentAttributes& from);
+
+  inline ContainerComponentAttributes& operator=(const ContainerComponentAttributes& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ContainerComponentAttributes(ContainerComponentAttributes&& from) noexcept
+    : ContainerComponentAttributes() {
+    *this = ::std::move(from);
+  }
+
+  inline ContainerComponentAttributes& operator=(ContainerComponentAttributes&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ContainerComponentAttributes& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ContainerComponentAttributes* internal_default_instance() {
+    return reinterpret_cast<const ContainerComponentAttributes*>(
+               &_ContainerComponentAttributes_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    6;
+
+  void Swap(ContainerComponentAttributes* other);
+  friend void swap(ContainerComponentAttributes& a, ContainerComponentAttributes& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ContainerComponentAttributes* New() const final {
+    return CreateMaybeMessage<ContainerComponentAttributes>(nullptr);
+  }
+
+  ContainerComponentAttributes* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ContainerComponentAttributes>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ContainerComponentAttributes& from);
+  void MergeFrom(const ContainerComponentAttributes& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ContainerComponentAttributes* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string physical_label = 1;
+  void clear_physical_label();
+  static const int kPhysicalLabelFieldNumber = 1;
+  const ::std::string& physical_label() const;
+  void set_physical_label(const ::std::string& value);
+  #if LANG_CXX11
+  void set_physical_label(::std::string&& value);
+  #endif
+  void set_physical_label(const char* value);
+  void set_physical_label(const char* value, size_t size);
+  ::std::string* mutable_physical_label();
+  ::std::string* release_physical_label();
+  void set_allocated_physical_label(::std::string* physical_label);
+
+  // @@protoc_insertion_point(class_scope:dmi.ContainerComponentAttributes)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr physical_label_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_2eproto;
+};
+// -------------------------------------------------------------------
+
+class PsuComponentAttributes final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.PsuComponentAttributes) */ {
+ public:
+  PsuComponentAttributes();
+  virtual ~PsuComponentAttributes();
+
+  PsuComponentAttributes(const PsuComponentAttributes& from);
+
+  inline PsuComponentAttributes& operator=(const PsuComponentAttributes& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  PsuComponentAttributes(PsuComponentAttributes&& from) noexcept
+    : PsuComponentAttributes() {
+    *this = ::std::move(from);
+  }
+
+  inline PsuComponentAttributes& operator=(PsuComponentAttributes&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const PsuComponentAttributes& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const PsuComponentAttributes* internal_default_instance() {
+    return reinterpret_cast<const PsuComponentAttributes*>(
+               &_PsuComponentAttributes_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    7;
+
+  void Swap(PsuComponentAttributes* other);
+  friend void swap(PsuComponentAttributes& a, PsuComponentAttributes& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline PsuComponentAttributes* New() const final {
+    return CreateMaybeMessage<PsuComponentAttributes>(nullptr);
+  }
+
+  PsuComponentAttributes* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<PsuComponentAttributes>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const PsuComponentAttributes& from);
+  void MergeFrom(const PsuComponentAttributes& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(PsuComponentAttributes* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef PsuComponentAttributes_SupportedVoltage SupportedVoltage;
+  static const SupportedVoltage SUPPORTED_VOLTAGE_UNDEFINED =
+    PsuComponentAttributes_SupportedVoltage_SUPPORTED_VOLTAGE_UNDEFINED;
+  static const SupportedVoltage V48 =
+    PsuComponentAttributes_SupportedVoltage_V48;
+  static const SupportedVoltage V230 =
+    PsuComponentAttributes_SupportedVoltage_V230;
+  static const SupportedVoltage V115 =
+    PsuComponentAttributes_SupportedVoltage_V115;
+  static inline bool SupportedVoltage_IsValid(int value) {
+    return PsuComponentAttributes_SupportedVoltage_IsValid(value);
+  }
+  static const SupportedVoltage SupportedVoltage_MIN =
+    PsuComponentAttributes_SupportedVoltage_SupportedVoltage_MIN;
+  static const SupportedVoltage SupportedVoltage_MAX =
+    PsuComponentAttributes_SupportedVoltage_SupportedVoltage_MAX;
+  static const int SupportedVoltage_ARRAYSIZE =
+    PsuComponentAttributes_SupportedVoltage_SupportedVoltage_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  SupportedVoltage_descriptor() {
+    return PsuComponentAttributes_SupportedVoltage_descriptor();
+  }
+  static inline const ::std::string& SupportedVoltage_Name(SupportedVoltage value) {
+    return PsuComponentAttributes_SupportedVoltage_Name(value);
+  }
+  static inline bool SupportedVoltage_Parse(const ::std::string& name,
+      SupportedVoltage* value) {
+    return PsuComponentAttributes_SupportedVoltage_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.PsuComponentAttributes.SupportedVoltage supported_voltage = 1;
+  void clear_supported_voltage();
+  static const int kSupportedVoltageFieldNumber = 1;
+  ::dmi::PsuComponentAttributes_SupportedVoltage supported_voltage() const;
+  void set_supported_voltage(::dmi::PsuComponentAttributes_SupportedVoltage value);
+
+  // @@protoc_insertion_point(class_scope:dmi.PsuComponentAttributes)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  int supported_voltage_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_2eproto;
+};
+// -------------------------------------------------------------------
+
+class TransceiverComponentsAttributes final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.TransceiverComponentsAttributes) */ {
+ public:
+  TransceiverComponentsAttributes();
+  virtual ~TransceiverComponentsAttributes();
+
+  TransceiverComponentsAttributes(const TransceiverComponentsAttributes& from);
+
+  inline TransceiverComponentsAttributes& operator=(const TransceiverComponentsAttributes& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  TransceiverComponentsAttributes(TransceiverComponentsAttributes&& from) noexcept
+    : TransceiverComponentsAttributes() {
+    *this = ::std::move(from);
+  }
+
+  inline TransceiverComponentsAttributes& operator=(TransceiverComponentsAttributes&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const TransceiverComponentsAttributes& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const TransceiverComponentsAttributes* internal_default_instance() {
+    return reinterpret_cast<const TransceiverComponentsAttributes*>(
+               &_TransceiverComponentsAttributes_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    8;
+
+  void Swap(TransceiverComponentsAttributes* other);
+  friend void swap(TransceiverComponentsAttributes& a, TransceiverComponentsAttributes& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline TransceiverComponentsAttributes* New() const final {
+    return CreateMaybeMessage<TransceiverComponentsAttributes>(nullptr);
+  }
+
+  TransceiverComponentsAttributes* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<TransceiverComponentsAttributes>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const TransceiverComponentsAttributes& from);
+  void MergeFrom(const TransceiverComponentsAttributes& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(TransceiverComponentsAttributes* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef TransceiverComponentsAttributes_FormFactor FormFactor;
+  static const FormFactor FORM_FACTOR_UNKNOWN =
+    TransceiverComponentsAttributes_FormFactor_FORM_FACTOR_UNKNOWN;
+  static const FormFactor QSFP =
+    TransceiverComponentsAttributes_FormFactor_QSFP;
+  static const FormFactor QSFP_PLUS =
+    TransceiverComponentsAttributes_FormFactor_QSFP_PLUS;
+  static const FormFactor QSFP28 =
+    TransceiverComponentsAttributes_FormFactor_QSFP28;
+  static const FormFactor SFP =
+    TransceiverComponentsAttributes_FormFactor_SFP;
+  static const FormFactor SFP_PLUS =
+    TransceiverComponentsAttributes_FormFactor_SFP_PLUS;
+  static const FormFactor XFP =
+    TransceiverComponentsAttributes_FormFactor_XFP;
+  static const FormFactor CFP4 =
+    TransceiverComponentsAttributes_FormFactor_CFP4;
+  static const FormFactor CFP2 =
+    TransceiverComponentsAttributes_FormFactor_CFP2;
+  static const FormFactor CPAK =
+    TransceiverComponentsAttributes_FormFactor_CPAK;
+  static const FormFactor X2 =
+    TransceiverComponentsAttributes_FormFactor_X2;
+  static const FormFactor OTHER =
+    TransceiverComponentsAttributes_FormFactor_OTHER;
+  static const FormFactor CFP =
+    TransceiverComponentsAttributes_FormFactor_CFP;
+  static const FormFactor CFP2_ACO =
+    TransceiverComponentsAttributes_FormFactor_CFP2_ACO;
+  static const FormFactor CFP2_DCO =
+    TransceiverComponentsAttributes_FormFactor_CFP2_DCO;
+  static inline bool FormFactor_IsValid(int value) {
+    return TransceiverComponentsAttributes_FormFactor_IsValid(value);
+  }
+  static const FormFactor FormFactor_MIN =
+    TransceiverComponentsAttributes_FormFactor_FormFactor_MIN;
+  static const FormFactor FormFactor_MAX =
+    TransceiverComponentsAttributes_FormFactor_FormFactor_MAX;
+  static const int FormFactor_ARRAYSIZE =
+    TransceiverComponentsAttributes_FormFactor_FormFactor_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  FormFactor_descriptor() {
+    return TransceiverComponentsAttributes_FormFactor_descriptor();
+  }
+  static inline const ::std::string& FormFactor_Name(FormFactor value) {
+    return TransceiverComponentsAttributes_FormFactor_Name(value);
+  }
+  static inline bool FormFactor_Parse(const ::std::string& name,
+      FormFactor* value) {
+    return TransceiverComponentsAttributes_FormFactor_Parse(name, value);
+  }
+
+  typedef TransceiverComponentsAttributes_Type Type;
+  static const Type TYPE_UNKNOWN =
+    TransceiverComponentsAttributes_Type_TYPE_UNKNOWN;
+  static const Type ETHERNET =
+    TransceiverComponentsAttributes_Type_ETHERNET;
+  static const Type GPON =
+    TransceiverComponentsAttributes_Type_GPON;
+  static const Type XGPON =
+    TransceiverComponentsAttributes_Type_XGPON;
+  static const Type XGSPON =
+    TransceiverComponentsAttributes_Type_XGSPON;
+  static const Type CPON =
+    TransceiverComponentsAttributes_Type_CPON;
+  static const Type NG_PON2 =
+    TransceiverComponentsAttributes_Type_NG_PON2;
+  static const Type EPON =
+    TransceiverComponentsAttributes_Type_EPON;
+  static inline bool Type_IsValid(int value) {
+    return TransceiverComponentsAttributes_Type_IsValid(value);
+  }
+  static const Type Type_MIN =
+    TransceiverComponentsAttributes_Type_Type_MIN;
+  static const Type Type_MAX =
+    TransceiverComponentsAttributes_Type_Type_MAX;
+  static const int Type_ARRAYSIZE =
+    TransceiverComponentsAttributes_Type_Type_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Type_descriptor() {
+    return TransceiverComponentsAttributes_Type_descriptor();
+  }
+  static inline const ::std::string& Type_Name(Type value) {
+    return TransceiverComponentsAttributes_Type_Name(value);
+  }
+  static inline bool Type_Parse(const ::std::string& name,
+      Type* value) {
+    return TransceiverComponentsAttributes_Type_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // repeated uint32 rx_wavelength = 5;
+  int rx_wavelength_size() const;
+  void clear_rx_wavelength();
+  static const int kRxWavelengthFieldNumber = 5;
+  ::google::protobuf::uint32 rx_wavelength(int index) const;
+  void set_rx_wavelength(int index, ::google::protobuf::uint32 value);
+  void add_rx_wavelength(::google::protobuf::uint32 value);
+  const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >&
+      rx_wavelength() const;
+  ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >*
+      mutable_rx_wavelength();
+
+  // repeated uint32 tx_wavelength = 6;
+  int tx_wavelength_size() const;
+  void clear_tx_wavelength();
+  static const int kTxWavelengthFieldNumber = 6;
+  ::google::protobuf::uint32 tx_wavelength(int index) const;
+  void set_tx_wavelength(int index, ::google::protobuf::uint32 value);
+  void add_tx_wavelength(::google::protobuf::uint32 value);
+  const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >&
+      tx_wavelength() const;
+  ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >*
+      mutable_tx_wavelength();
+
+  // .dmi.TransceiverComponentsAttributes.FormFactor form_factor = 1;
+  void clear_form_factor();
+  static const int kFormFactorFieldNumber = 1;
+  ::dmi::TransceiverComponentsAttributes_FormFactor form_factor() const;
+  void set_form_factor(::dmi::TransceiverComponentsAttributes_FormFactor value);
+
+  // .dmi.TransceiverComponentsAttributes.Type trans_type = 2;
+  void clear_trans_type();
+  static const int kTransTypeFieldNumber = 2;
+  ::dmi::TransceiverComponentsAttributes_Type trans_type() const;
+  void set_trans_type(::dmi::TransceiverComponentsAttributes_Type value);
+
+  // uint32 max_distance = 3;
+  void clear_max_distance();
+  static const int kMaxDistanceFieldNumber = 3;
+  ::google::protobuf::uint32 max_distance() const;
+  void set_max_distance(::google::protobuf::uint32 value);
+
+  // .dmi.ValueScale max_distance_scale = 4;
+  void clear_max_distance_scale();
+  static const int kMaxDistanceScaleFieldNumber = 4;
+  ::dmi::ValueScale max_distance_scale() const;
+  void set_max_distance_scale(::dmi::ValueScale value);
+
+  // .dmi.ValueScale wavelength_scale = 7;
+  void clear_wavelength_scale();
+  static const int kWavelengthScaleFieldNumber = 7;
+  ::dmi::ValueScale wavelength_scale() const;
+  void set_wavelength_scale(::dmi::ValueScale value);
+
+  // @@protoc_insertion_point(class_scope:dmi.TransceiverComponentsAttributes)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::RepeatedField< ::google::protobuf::uint32 > rx_wavelength_;
+  mutable std::atomic<int> _rx_wavelength_cached_byte_size_;
+  ::google::protobuf::RepeatedField< ::google::protobuf::uint32 > tx_wavelength_;
+  mutable std::atomic<int> _tx_wavelength_cached_byte_size_;
+  int form_factor_;
+  int trans_type_;
+  ::google::protobuf::uint32 max_distance_;
+  int max_distance_scale_;
+  int wavelength_scale_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_2eproto;
+};
+// -------------------------------------------------------------------
+
+class Component final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.Component) */ {
+ public:
+  Component();
+  virtual ~Component();
+
+  Component(const Component& from);
+
+  inline Component& operator=(const Component& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Component(Component&& from) noexcept
+    : Component() {
+    *this = ::std::move(from);
+  }
+
+  inline Component& operator=(Component&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const Component& default_instance();
+
+  enum SpecificCase {
+    kPortAttr = 50,
+    kContainerAttr = 51,
+    kPsuAttr = 52,
+    kTransceiverAttr = 53,
+    SPECIFIC_NOT_SET = 0,
+  };
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Component* internal_default_instance() {
+    return reinterpret_cast<const Component*>(
+               &_Component_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    9;
+
+  void Swap(Component* other);
+  friend void swap(Component& a, Component& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Component* New() const final {
+    return CreateMaybeMessage<Component>(nullptr);
+  }
+
+  Component* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<Component>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const Component& from);
+  void MergeFrom(const Component& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Component* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated .dmi.Component children = 6;
+  int children_size() const;
+  void clear_children();
+  static const int kChildrenFieldNumber = 6;
+  ::dmi::Component* mutable_children(int index);
+  ::google::protobuf::RepeatedPtrField< ::dmi::Component >*
+      mutable_children();
+  const ::dmi::Component& children(int index) const;
+  ::dmi::Component* add_children();
+  const ::google::protobuf::RepeatedPtrField< ::dmi::Component >&
+      children() const;
+
+  // repeated .dmi.ComponentSensorData sensor_data = 20;
+  int sensor_data_size() const;
+  void clear_sensor_data();
+  static const int kSensorDataFieldNumber = 20;
+  ::dmi::ComponentSensorData* mutable_sensor_data(int index);
+  ::google::protobuf::RepeatedPtrField< ::dmi::ComponentSensorData >*
+      mutable_sensor_data();
+  const ::dmi::ComponentSensorData& sensor_data(int index) const;
+  ::dmi::ComponentSensorData* add_sensor_data();
+  const ::google::protobuf::RepeatedPtrField< ::dmi::ComponentSensorData >&
+      sensor_data() const;
+
+  // string name = 1;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_name(::std::string&& value);
+  #endif
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // string description = 3;
+  void clear_description();
+  static const int kDescriptionFieldNumber = 3;
+  const ::std::string& description() const;
+  void set_description(const ::std::string& value);
+  #if LANG_CXX11
+  void set_description(::std::string&& value);
+  #endif
+  void set_description(const char* value);
+  void set_description(const char* value, size_t size);
+  ::std::string* mutable_description();
+  ::std::string* release_description();
+  void set_allocated_description(::std::string* description);
+
+  // string parent = 4;
+  void clear_parent();
+  static const int kParentFieldNumber = 4;
+  const ::std::string& parent() const;
+  void set_parent(const ::std::string& value);
+  #if LANG_CXX11
+  void set_parent(::std::string&& value);
+  #endif
+  void set_parent(const char* value);
+  void set_parent(const char* value, size_t size);
+  ::std::string* mutable_parent();
+  ::std::string* release_parent();
+  void set_allocated_parent(::std::string* parent);
+
+  // string hardware_rev = 7;
+  void clear_hardware_rev();
+  static const int kHardwareRevFieldNumber = 7;
+  const ::std::string& hardware_rev() const;
+  void set_hardware_rev(const ::std::string& value);
+  #if LANG_CXX11
+  void set_hardware_rev(::std::string&& value);
+  #endif
+  void set_hardware_rev(const char* value);
+  void set_hardware_rev(const char* value, size_t size);
+  ::std::string* mutable_hardware_rev();
+  ::std::string* release_hardware_rev();
+  void set_allocated_hardware_rev(::std::string* hardware_rev);
+
+  // string firmware_rev = 8;
+  void clear_firmware_rev();
+  static const int kFirmwareRevFieldNumber = 8;
+  const ::std::string& firmware_rev() const;
+  void set_firmware_rev(const ::std::string& value);
+  #if LANG_CXX11
+  void set_firmware_rev(::std::string&& value);
+  #endif
+  void set_firmware_rev(const char* value);
+  void set_firmware_rev(const char* value, size_t size);
+  ::std::string* mutable_firmware_rev();
+  ::std::string* release_firmware_rev();
+  void set_allocated_firmware_rev(::std::string* firmware_rev);
+
+  // string software_rev = 9;
+  void clear_software_rev();
+  static const int kSoftwareRevFieldNumber = 9;
+  const ::std::string& software_rev() const;
+  void set_software_rev(const ::std::string& value);
+  #if LANG_CXX11
+  void set_software_rev(::std::string&& value);
+  #endif
+  void set_software_rev(const char* value);
+  void set_software_rev(const char* value, size_t size);
+  ::std::string* mutable_software_rev();
+  ::std::string* release_software_rev();
+  void set_allocated_software_rev(::std::string* software_rev);
+
+  // string serial_num = 10;
+  void clear_serial_num();
+  static const int kSerialNumFieldNumber = 10;
+  const ::std::string& serial_num() const;
+  void set_serial_num(const ::std::string& value);
+  #if LANG_CXX11
+  void set_serial_num(::std::string&& value);
+  #endif
+  void set_serial_num(const char* value);
+  void set_serial_num(const char* value, size_t size);
+  ::std::string* mutable_serial_num();
+  ::std::string* release_serial_num();
+  void set_allocated_serial_num(::std::string* serial_num);
+
+  // string mfg_name = 11;
+  void clear_mfg_name();
+  static const int kMfgNameFieldNumber = 11;
+  const ::std::string& mfg_name() const;
+  void set_mfg_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_mfg_name(::std::string&& value);
+  #endif
+  void set_mfg_name(const char* value);
+  void set_mfg_name(const char* value, size_t size);
+  ::std::string* mutable_mfg_name();
+  ::std::string* release_mfg_name();
+  void set_allocated_mfg_name(::std::string* mfg_name);
+
+  // string model_name = 12;
+  void clear_model_name();
+  static const int kModelNameFieldNumber = 12;
+  const ::std::string& model_name() const;
+  void set_model_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_model_name(::std::string&& value);
+  #endif
+  void set_model_name(const char* value);
+  void set_model_name(const char* value, size_t size);
+  ::std::string* mutable_model_name();
+  ::std::string* release_model_name();
+  void set_allocated_model_name(::std::string* model_name);
+
+  // string alias = 13;
+  void clear_alias();
+  static const int kAliasFieldNumber = 13;
+  const ::std::string& alias() const;
+  void set_alias(const ::std::string& value);
+  #if LANG_CXX11
+  void set_alias(::std::string&& value);
+  #endif
+  void set_alias(const char* value);
+  void set_alias(const char* value, size_t size);
+  ::std::string* mutable_alias();
+  ::std::string* release_alias();
+  void set_allocated_alias(::std::string* alias);
+
+  // string asset_id = 14;
+  void clear_asset_id();
+  static const int kAssetIdFieldNumber = 14;
+  const ::std::string& asset_id() const;
+  void set_asset_id(const ::std::string& value);
+  #if LANG_CXX11
+  void set_asset_id(::std::string&& value);
+  #endif
+  void set_asset_id(const char* value);
+  void set_asset_id(const char* value, size_t size);
+  ::std::string* mutable_asset_id();
+  ::std::string* release_asset_id();
+  void set_allocated_asset_id(::std::string* asset_id);
+
+  // .google.protobuf.Timestamp mfg_date = 16;
+  bool has_mfg_date() const;
+  void clear_mfg_date();
+  static const int kMfgDateFieldNumber = 16;
+  const ::google::protobuf::Timestamp& mfg_date() const;
+  ::google::protobuf::Timestamp* release_mfg_date();
+  ::google::protobuf::Timestamp* mutable_mfg_date();
+  void set_allocated_mfg_date(::google::protobuf::Timestamp* mfg_date);
+
+  // .dmi.Uri uri = 17;
+  bool has_uri() const;
+  void clear_uri();
+  static const int kUriFieldNumber = 17;
+  const ::dmi::Uri& uri() const;
+  ::dmi::Uri* release_uri();
+  ::dmi::Uri* mutable_uri();
+  void set_allocated_uri(::dmi::Uri* uri);
+
+  // .dmi.Uuid uuid = 18;
+  bool has_uuid() const;
+  void clear_uuid();
+  static const int kUuidFieldNumber = 18;
+  const ::dmi::Uuid& uuid() const;
+  ::dmi::Uuid* release_uuid();
+  ::dmi::Uuid* mutable_uuid();
+  void set_allocated_uuid(::dmi::Uuid* uuid);
+
+  // .dmi.ComponentState state = 19;
+  bool has_state() const;
+  void clear_state();
+  static const int kStateFieldNumber = 19;
+  const ::dmi::ComponentState& state() const;
+  ::dmi::ComponentState* release_state();
+  ::dmi::ComponentState* mutable_state();
+  void set_allocated_state(::dmi::ComponentState* state);
+
+  // .dmi.ComponentType class = 2;
+  void clear_class_();
+  static const int kClassFieldNumber = 2;
+  ::dmi::ComponentType class_() const;
+  void set_class_(::dmi::ComponentType value);
+
+  // int32 parent_rel_pos = 5;
+  void clear_parent_rel_pos();
+  static const int kParentRelPosFieldNumber = 5;
+  ::google::protobuf::int32 parent_rel_pos() const;
+  void set_parent_rel_pos(::google::protobuf::int32 value);
+
+  // bool is_fru = 15;
+  void clear_is_fru();
+  static const int kIsFruFieldNumber = 15;
+  bool is_fru() const;
+  void set_is_fru(bool value);
+
+  // .dmi.PortComponentAttributes port_attr = 50;
+  bool has_port_attr() const;
+  void clear_port_attr();
+  static const int kPortAttrFieldNumber = 50;
+  const ::dmi::PortComponentAttributes& port_attr() const;
+  ::dmi::PortComponentAttributes* release_port_attr();
+  ::dmi::PortComponentAttributes* mutable_port_attr();
+  void set_allocated_port_attr(::dmi::PortComponentAttributes* port_attr);
+
+  // .dmi.ContainerComponentAttributes container_attr = 51;
+  bool has_container_attr() const;
+  void clear_container_attr();
+  static const int kContainerAttrFieldNumber = 51;
+  const ::dmi::ContainerComponentAttributes& container_attr() const;
+  ::dmi::ContainerComponentAttributes* release_container_attr();
+  ::dmi::ContainerComponentAttributes* mutable_container_attr();
+  void set_allocated_container_attr(::dmi::ContainerComponentAttributes* container_attr);
+
+  // .dmi.PsuComponentAttributes psu_attr = 52;
+  bool has_psu_attr() const;
+  void clear_psu_attr();
+  static const int kPsuAttrFieldNumber = 52;
+  const ::dmi::PsuComponentAttributes& psu_attr() const;
+  ::dmi::PsuComponentAttributes* release_psu_attr();
+  ::dmi::PsuComponentAttributes* mutable_psu_attr();
+  void set_allocated_psu_attr(::dmi::PsuComponentAttributes* psu_attr);
+
+  // .dmi.TransceiverComponentsAttributes transceiver_attr = 53;
+  bool has_transceiver_attr() const;
+  void clear_transceiver_attr();
+  static const int kTransceiverAttrFieldNumber = 53;
+  const ::dmi::TransceiverComponentsAttributes& transceiver_attr() const;
+  ::dmi::TransceiverComponentsAttributes* release_transceiver_attr();
+  ::dmi::TransceiverComponentsAttributes* mutable_transceiver_attr();
+  void set_allocated_transceiver_attr(::dmi::TransceiverComponentsAttributes* transceiver_attr);
+
+  void clear_specific();
+  SpecificCase specific_case() const;
+  // @@protoc_insertion_point(class_scope:dmi.Component)
+ private:
+  class HasBitSetters;
+  void set_has_port_attr();
+  void set_has_container_attr();
+  void set_has_psu_attr();
+  void set_has_transceiver_attr();
+
+  inline bool has_specific() const;
+  inline void clear_has_specific();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::RepeatedPtrField< ::dmi::Component > children_;
+  ::google::protobuf::RepeatedPtrField< ::dmi::ComponentSensorData > sensor_data_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::internal::ArenaStringPtr description_;
+  ::google::protobuf::internal::ArenaStringPtr parent_;
+  ::google::protobuf::internal::ArenaStringPtr hardware_rev_;
+  ::google::protobuf::internal::ArenaStringPtr firmware_rev_;
+  ::google::protobuf::internal::ArenaStringPtr software_rev_;
+  ::google::protobuf::internal::ArenaStringPtr serial_num_;
+  ::google::protobuf::internal::ArenaStringPtr mfg_name_;
+  ::google::protobuf::internal::ArenaStringPtr model_name_;
+  ::google::protobuf::internal::ArenaStringPtr alias_;
+  ::google::protobuf::internal::ArenaStringPtr asset_id_;
+  ::google::protobuf::Timestamp* mfg_date_;
+  ::dmi::Uri* uri_;
+  ::dmi::Uuid* uuid_;
+  ::dmi::ComponentState* state_;
+  int class__;
+  ::google::protobuf::int32 parent_rel_pos_;
+  bool is_fru_;
+  union SpecificUnion {
+    SpecificUnion() {}
+    ::dmi::PortComponentAttributes* port_attr_;
+    ::dmi::ContainerComponentAttributes* container_attr_;
+    ::dmi::PsuComponentAttributes* psu_attr_;
+    ::dmi::TransceiverComponentsAttributes* transceiver_attr_;
+  } specific_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  ::google::protobuf::uint32 _oneof_case_[1];
+
+  friend struct ::TableStruct_dmi_2fhw_2eproto;
+};
+// -------------------------------------------------------------------
+
+class Hardware final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.Hardware) */ {
+ public:
+  Hardware();
+  virtual ~Hardware();
+
+  Hardware(const Hardware& from);
+
+  inline Hardware& operator=(const Hardware& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Hardware(Hardware&& from) noexcept
+    : Hardware() {
+    *this = ::std::move(from);
+  }
+
+  inline Hardware& operator=(Hardware&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const Hardware& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Hardware* internal_default_instance() {
+    return reinterpret_cast<const Hardware*>(
+               &_Hardware_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    10;
+
+  void Swap(Hardware* other);
+  friend void swap(Hardware& a, Hardware& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Hardware* New() const final {
+    return CreateMaybeMessage<Hardware>(nullptr);
+  }
+
+  Hardware* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<Hardware>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const Hardware& from);
+  void MergeFrom(const Hardware& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Hardware* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .google.protobuf.Timestamp last_change = 1;
+  bool has_last_change() const;
+  void clear_last_change();
+  static const int kLastChangeFieldNumber = 1;
+  const ::google::protobuf::Timestamp& last_change() const;
+  ::google::protobuf::Timestamp* release_last_change();
+  ::google::protobuf::Timestamp* mutable_last_change();
+  void set_allocated_last_change(::google::protobuf::Timestamp* last_change);
+
+  // .dmi.Component root = 2;
+  bool has_root() const;
+  void clear_root();
+  static const int kRootFieldNumber = 2;
+  const ::dmi::Component& root() const;
+  ::dmi::Component* release_root();
+  ::dmi::Component* mutable_root();
+  void set_allocated_root(::dmi::Component* root);
+
+  // .google.protobuf.Timestamp last_booted = 3;
+  bool has_last_booted() const;
+  void clear_last_booted();
+  static const int kLastBootedFieldNumber = 3;
+  const ::google::protobuf::Timestamp& last_booted() const;
+  ::google::protobuf::Timestamp* release_last_booted();
+  ::google::protobuf::Timestamp* mutable_last_booted();
+  void set_allocated_last_booted(::google::protobuf::Timestamp* last_booted);
+
+  // @@protoc_insertion_point(class_scope:dmi.Hardware)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::Timestamp* last_change_;
+  ::dmi::Component* root_;
+  ::google::protobuf::Timestamp* last_booted_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ModifiableComponent final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ModifiableComponent) */ {
+ public:
+  ModifiableComponent();
+  virtual ~ModifiableComponent();
+
+  ModifiableComponent(const ModifiableComponent& from);
+
+  inline ModifiableComponent& operator=(const ModifiableComponent& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ModifiableComponent(ModifiableComponent&& from) noexcept
+    : ModifiableComponent() {
+    *this = ::std::move(from);
+  }
+
+  inline ModifiableComponent& operator=(ModifiableComponent&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ModifiableComponent& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ModifiableComponent* internal_default_instance() {
+    return reinterpret_cast<const ModifiableComponent*>(
+               &_ModifiableComponent_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    11;
+
+  void Swap(ModifiableComponent* other);
+  friend void swap(ModifiableComponent& a, ModifiableComponent& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ModifiableComponent* New() const final {
+    return CreateMaybeMessage<ModifiableComponent>(nullptr);
+  }
+
+  ModifiableComponent* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ModifiableComponent>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ModifiableComponent& from);
+  void MergeFrom(const ModifiableComponent& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ModifiableComponent* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string name = 1;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_name(::std::string&& value);
+  #endif
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // string alias = 5;
+  void clear_alias();
+  static const int kAliasFieldNumber = 5;
+  const ::std::string& alias() const;
+  void set_alias(const ::std::string& value);
+  #if LANG_CXX11
+  void set_alias(::std::string&& value);
+  #endif
+  void set_alias(const char* value);
+  void set_alias(const char* value, size_t size);
+  ::std::string* mutable_alias();
+  ::std::string* release_alias();
+  void set_allocated_alias(::std::string* alias);
+
+  // string asset_id = 6;
+  void clear_asset_id();
+  static const int kAssetIdFieldNumber = 6;
+  const ::std::string& asset_id() const;
+  void set_asset_id(const ::std::string& value);
+  #if LANG_CXX11
+  void set_asset_id(::std::string&& value);
+  #endif
+  void set_asset_id(const char* value);
+  void set_asset_id(const char* value, size_t size);
+  ::std::string* mutable_asset_id();
+  ::std::string* release_asset_id();
+  void set_allocated_asset_id(::std::string* asset_id);
+
+  // .dmi.Component parent = 3;
+  bool has_parent() const;
+  void clear_parent();
+  static const int kParentFieldNumber = 3;
+  const ::dmi::Component& parent() const;
+  ::dmi::Component* release_parent();
+  ::dmi::Component* mutable_parent();
+  void set_allocated_parent(::dmi::Component* parent);
+
+  // .dmi.Uri uri = 7;
+  bool has_uri() const;
+  void clear_uri();
+  static const int kUriFieldNumber = 7;
+  const ::dmi::Uri& uri() const;
+  ::dmi::Uri* release_uri();
+  ::dmi::Uri* mutable_uri();
+  void set_allocated_uri(::dmi::Uri* uri);
+
+  // .dmi.ComponentType class = 2;
+  void clear_class_();
+  static const int kClassFieldNumber = 2;
+  ::dmi::ComponentType class_() const;
+  void set_class_(::dmi::ComponentType value);
+
+  // int32 parent_rel_pos = 4;
+  void clear_parent_rel_pos();
+  static const int kParentRelPosFieldNumber = 4;
+  ::google::protobuf::int32 parent_rel_pos() const;
+  void set_parent_rel_pos(::google::protobuf::int32 value);
+
+  // .dmi.ComponentAdminState admin_state = 8;
+  void clear_admin_state();
+  static const int kAdminStateFieldNumber = 8;
+  ::dmi::ComponentAdminState admin_state() const;
+  void set_admin_state(::dmi::ComponentAdminState value);
+
+  // @@protoc_insertion_point(class_scope:dmi.ModifiableComponent)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  ::google::protobuf::internal::ArenaStringPtr alias_;
+  ::google::protobuf::internal::ArenaStringPtr asset_id_;
+  ::dmi::Component* parent_;
+  ::dmi::Uri* uri_;
+  int class__;
+  ::google::protobuf::int32 parent_rel_pos_;
+  int admin_state_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_2eproto;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// Uuid
+
+// string uuid = 1;
+inline void Uuid::clear_uuid() {
+  uuid_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Uuid::uuid() const {
+  // @@protoc_insertion_point(field_get:dmi.Uuid.uuid)
+  return uuid_.GetNoArena();
+}
+inline void Uuid::set_uuid(const ::std::string& value) {
+  
+  uuid_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Uuid.uuid)
+}
+#if LANG_CXX11
+inline void Uuid::set_uuid(::std::string&& value) {
+  
+  uuid_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Uuid.uuid)
+}
+#endif
+inline void Uuid::set_uuid(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  uuid_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Uuid.uuid)
+}
+inline void Uuid::set_uuid(const char* value, size_t size) {
+  
+  uuid_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Uuid.uuid)
+}
+inline ::std::string* Uuid::mutable_uuid() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Uuid.uuid)
+  return uuid_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Uuid::release_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.Uuid.uuid)
+  
+  return uuid_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Uuid::set_allocated_uuid(::std::string* uuid) {
+  if (uuid != nullptr) {
+    
+  } else {
+    
+  }
+  uuid_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), uuid);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Uuid.uuid)
+}
+
+// -------------------------------------------------------------------
+
+// HardwareID
+
+// .dmi.Uuid uuid = 1;
+inline bool HardwareID::has_uuid() const {
+  return this != internal_default_instance() && uuid_ != nullptr;
+}
+inline void HardwareID::clear_uuid() {
+  if (GetArenaNoVirtual() == nullptr && uuid_ != nullptr) {
+    delete uuid_;
+  }
+  uuid_ = nullptr;
+}
+inline const ::dmi::Uuid& HardwareID::uuid() const {
+  const ::dmi::Uuid* p = uuid_;
+  // @@protoc_insertion_point(field_get:dmi.HardwareID.uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* HardwareID::release_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.HardwareID.uuid)
+  
+  ::dmi::Uuid* temp = uuid_;
+  uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* HardwareID::mutable_uuid() {
+  
+  if (uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.HardwareID.uuid)
+  return uuid_;
+}
+inline void HardwareID::set_allocated_uuid(::dmi::Uuid* uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete uuid_;
+  }
+  if (uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  uuid_ = uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.HardwareID.uuid)
+}
+
+// -------------------------------------------------------------------
+
+// Uri
+
+// string uri = 1;
+inline void Uri::clear_uri() {
+  uri_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Uri::uri() const {
+  // @@protoc_insertion_point(field_get:dmi.Uri.uri)
+  return uri_.GetNoArena();
+}
+inline void Uri::set_uri(const ::std::string& value) {
+  
+  uri_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Uri.uri)
+}
+#if LANG_CXX11
+inline void Uri::set_uri(::std::string&& value) {
+  
+  uri_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Uri.uri)
+}
+#endif
+inline void Uri::set_uri(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  uri_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Uri.uri)
+}
+inline void Uri::set_uri(const char* value, size_t size) {
+  
+  uri_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Uri.uri)
+}
+inline ::std::string* Uri::mutable_uri() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Uri.uri)
+  return uri_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Uri::release_uri() {
+  // @@protoc_insertion_point(field_release:dmi.Uri.uri)
+  
+  return uri_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Uri::set_allocated_uri(::std::string* uri) {
+  if (uri != nullptr) {
+    
+  } else {
+    
+  }
+  uri_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), uri);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Uri.uri)
+}
+
+// -------------------------------------------------------------------
+
+// ComponentState
+
+// .google.protobuf.Timestamp state_last_changed = 1;
+inline bool ComponentState::has_state_last_changed() const {
+  return this != internal_default_instance() && state_last_changed_ != nullptr;
+}
+inline const ::google::protobuf::Timestamp& ComponentState::state_last_changed() const {
+  const ::google::protobuf::Timestamp* p = state_last_changed_;
+  // @@protoc_insertion_point(field_get:dmi.ComponentState.state_last_changed)
+  return p != nullptr ? *p : *reinterpret_cast<const ::google::protobuf::Timestamp*>(
+      &::google::protobuf::_Timestamp_default_instance_);
+}
+inline ::google::protobuf::Timestamp* ComponentState::release_state_last_changed() {
+  // @@protoc_insertion_point(field_release:dmi.ComponentState.state_last_changed)
+  
+  ::google::protobuf::Timestamp* temp = state_last_changed_;
+  state_last_changed_ = nullptr;
+  return temp;
+}
+inline ::google::protobuf::Timestamp* ComponentState::mutable_state_last_changed() {
+  
+  if (state_last_changed_ == nullptr) {
+    auto* p = CreateMaybeMessage<::google::protobuf::Timestamp>(GetArenaNoVirtual());
+    state_last_changed_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ComponentState.state_last_changed)
+  return state_last_changed_;
+}
+inline void ComponentState::set_allocated_state_last_changed(::google::protobuf::Timestamp* state_last_changed) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(state_last_changed_);
+  }
+  if (state_last_changed) {
+    ::google::protobuf::Arena* submessage_arena =
+      reinterpret_cast<::google::protobuf::MessageLite*>(state_last_changed)->GetArena();
+    if (message_arena != submessage_arena) {
+      state_last_changed = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, state_last_changed, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  state_last_changed_ = state_last_changed;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ComponentState.state_last_changed)
+}
+
+// .dmi.ComponentAdminState admin_state = 2;
+inline void ComponentState::clear_admin_state() {
+  admin_state_ = 0;
+}
+inline ::dmi::ComponentAdminState ComponentState::admin_state() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentState.admin_state)
+  return static_cast< ::dmi::ComponentAdminState >(admin_state_);
+}
+inline void ComponentState::set_admin_state(::dmi::ComponentAdminState value) {
+  
+  admin_state_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ComponentState.admin_state)
+}
+
+// .dmi.ComponentOperState oper_state = 3;
+inline void ComponentState::clear_oper_state() {
+  oper_state_ = 0;
+}
+inline ::dmi::ComponentOperState ComponentState::oper_state() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentState.oper_state)
+  return static_cast< ::dmi::ComponentOperState >(oper_state_);
+}
+inline void ComponentState::set_oper_state(::dmi::ComponentOperState value) {
+  
+  oper_state_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ComponentState.oper_state)
+}
+
+// .dmi.ComponentUsageState usage_state = 4;
+inline void ComponentState::clear_usage_state() {
+  usage_state_ = 0;
+}
+inline ::dmi::ComponentUsageState ComponentState::usage_state() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentState.usage_state)
+  return static_cast< ::dmi::ComponentUsageState >(usage_state_);
+}
+inline void ComponentState::set_usage_state(::dmi::ComponentUsageState value) {
+  
+  usage_state_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ComponentState.usage_state)
+}
+
+// .dmi.ComponentAlarmState alarm_state = 5;
+inline void ComponentState::clear_alarm_state() {
+  alarm_state_ = 0;
+}
+inline ::dmi::ComponentAlarmState ComponentState::alarm_state() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentState.alarm_state)
+  return static_cast< ::dmi::ComponentAlarmState >(alarm_state_);
+}
+inline void ComponentState::set_alarm_state(::dmi::ComponentAlarmState value) {
+  
+  alarm_state_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ComponentState.alarm_state)
+}
+
+// .dmi.ComponentStandbyState standby_state = 6;
+inline void ComponentState::clear_standby_state() {
+  standby_state_ = 0;
+}
+inline ::dmi::ComponentStandbyState ComponentState::standby_state() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentState.standby_state)
+  return static_cast< ::dmi::ComponentStandbyState >(standby_state_);
+}
+inline void ComponentState::set_standby_state(::dmi::ComponentStandbyState value) {
+  
+  standby_state_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ComponentState.standby_state)
+}
+
+// -------------------------------------------------------------------
+
+// ComponentSensorData
+
+// int32 value = 1;
+inline void ComponentSensorData::clear_value() {
+  value_ = 0;
+}
+inline ::google::protobuf::int32 ComponentSensorData::value() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentSensorData.value)
+  return value_;
+}
+inline void ComponentSensorData::set_value(::google::protobuf::int32 value) {
+  
+  value_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ComponentSensorData.value)
+}
+
+// .dmi.DataValueType type = 2;
+inline void ComponentSensorData::clear_type() {
+  type_ = 0;
+}
+inline ::dmi::DataValueType ComponentSensorData::type() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentSensorData.type)
+  return static_cast< ::dmi::DataValueType >(type_);
+}
+inline void ComponentSensorData::set_type(::dmi::DataValueType value) {
+  
+  type_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ComponentSensorData.type)
+}
+
+// .dmi.ValueScale scale = 3;
+inline void ComponentSensorData::clear_scale() {
+  scale_ = 0;
+}
+inline ::dmi::ValueScale ComponentSensorData::scale() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentSensorData.scale)
+  return static_cast< ::dmi::ValueScale >(scale_);
+}
+inline void ComponentSensorData::set_scale(::dmi::ValueScale value) {
+  
+  scale_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ComponentSensorData.scale)
+}
+
+// int32 precision = 4;
+inline void ComponentSensorData::clear_precision() {
+  precision_ = 0;
+}
+inline ::google::protobuf::int32 ComponentSensorData::precision() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentSensorData.precision)
+  return precision_;
+}
+inline void ComponentSensorData::set_precision(::google::protobuf::int32 value) {
+  
+  precision_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ComponentSensorData.precision)
+}
+
+// .dmi.SensorStatus status = 5;
+inline void ComponentSensorData::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::SensorStatus ComponentSensorData::status() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentSensorData.status)
+  return static_cast< ::dmi::SensorStatus >(status_);
+}
+inline void ComponentSensorData::set_status(::dmi::SensorStatus value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ComponentSensorData.status)
+}
+
+// string units_display = 6;
+inline void ComponentSensorData::clear_units_display() {
+  units_display_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ComponentSensorData::units_display() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentSensorData.units_display)
+  return units_display_.GetNoArena();
+}
+inline void ComponentSensorData::set_units_display(const ::std::string& value) {
+  
+  units_display_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ComponentSensorData.units_display)
+}
+#if LANG_CXX11
+inline void ComponentSensorData::set_units_display(::std::string&& value) {
+  
+  units_display_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ComponentSensorData.units_display)
+}
+#endif
+inline void ComponentSensorData::set_units_display(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  units_display_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ComponentSensorData.units_display)
+}
+inline void ComponentSensorData::set_units_display(const char* value, size_t size) {
+  
+  units_display_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ComponentSensorData.units_display)
+}
+inline ::std::string* ComponentSensorData::mutable_units_display() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ComponentSensorData.units_display)
+  return units_display_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ComponentSensorData::release_units_display() {
+  // @@protoc_insertion_point(field_release:dmi.ComponentSensorData.units_display)
+  
+  return units_display_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ComponentSensorData::set_allocated_units_display(::std::string* units_display) {
+  if (units_display != nullptr) {
+    
+  } else {
+    
+  }
+  units_display_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), units_display);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ComponentSensorData.units_display)
+}
+
+// .google.protobuf.Timestamp timestamp = 7;
+inline bool ComponentSensorData::has_timestamp() const {
+  return this != internal_default_instance() && timestamp_ != nullptr;
+}
+inline const ::google::protobuf::Timestamp& ComponentSensorData::timestamp() const {
+  const ::google::protobuf::Timestamp* p = timestamp_;
+  // @@protoc_insertion_point(field_get:dmi.ComponentSensorData.timestamp)
+  return p != nullptr ? *p : *reinterpret_cast<const ::google::protobuf::Timestamp*>(
+      &::google::protobuf::_Timestamp_default_instance_);
+}
+inline ::google::protobuf::Timestamp* ComponentSensorData::release_timestamp() {
+  // @@protoc_insertion_point(field_release:dmi.ComponentSensorData.timestamp)
+  
+  ::google::protobuf::Timestamp* temp = timestamp_;
+  timestamp_ = nullptr;
+  return temp;
+}
+inline ::google::protobuf::Timestamp* ComponentSensorData::mutable_timestamp() {
+  
+  if (timestamp_ == nullptr) {
+    auto* p = CreateMaybeMessage<::google::protobuf::Timestamp>(GetArenaNoVirtual());
+    timestamp_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ComponentSensorData.timestamp)
+  return timestamp_;
+}
+inline void ComponentSensorData::set_allocated_timestamp(::google::protobuf::Timestamp* timestamp) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(timestamp_);
+  }
+  if (timestamp) {
+    ::google::protobuf::Arena* submessage_arena =
+      reinterpret_cast<::google::protobuf::MessageLite*>(timestamp)->GetArena();
+    if (message_arena != submessage_arena) {
+      timestamp = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, timestamp, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  timestamp_ = timestamp;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ComponentSensorData.timestamp)
+}
+
+// uint32 value_update_rate = 8;
+inline void ComponentSensorData::clear_value_update_rate() {
+  value_update_rate_ = 0u;
+}
+inline ::google::protobuf::uint32 ComponentSensorData::value_update_rate() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentSensorData.value_update_rate)
+  return value_update_rate_;
+}
+inline void ComponentSensorData::set_value_update_rate(::google::protobuf::uint32 value) {
+  
+  value_update_rate_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ComponentSensorData.value_update_rate)
+}
+
+// string data_type = 9;
+inline void ComponentSensorData::clear_data_type() {
+  data_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ComponentSensorData::data_type() const {
+  // @@protoc_insertion_point(field_get:dmi.ComponentSensorData.data_type)
+  return data_type_.GetNoArena();
+}
+inline void ComponentSensorData::set_data_type(const ::std::string& value) {
+  
+  data_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ComponentSensorData.data_type)
+}
+#if LANG_CXX11
+inline void ComponentSensorData::set_data_type(::std::string&& value) {
+  
+  data_type_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ComponentSensorData.data_type)
+}
+#endif
+inline void ComponentSensorData::set_data_type(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  data_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ComponentSensorData.data_type)
+}
+inline void ComponentSensorData::set_data_type(const char* value, size_t size) {
+  
+  data_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ComponentSensorData.data_type)
+}
+inline ::std::string* ComponentSensorData::mutable_data_type() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ComponentSensorData.data_type)
+  return data_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ComponentSensorData::release_data_type() {
+  // @@protoc_insertion_point(field_release:dmi.ComponentSensorData.data_type)
+  
+  return data_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ComponentSensorData::set_allocated_data_type(::std::string* data_type) {
+  if (data_type != nullptr) {
+    
+  } else {
+    
+  }
+  data_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), data_type);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ComponentSensorData.data_type)
+}
+
+// -------------------------------------------------------------------
+
+// PortComponentAttributes
+
+// .dmi.PortComponentAttributes.ConnectorType connector_type = 1;
+inline void PortComponentAttributes::clear_connector_type() {
+  connector_type_ = 0;
+}
+inline ::dmi::PortComponentAttributes_ConnectorType PortComponentAttributes::connector_type() const {
+  // @@protoc_insertion_point(field_get:dmi.PortComponentAttributes.connector_type)
+  return static_cast< ::dmi::PortComponentAttributes_ConnectorType >(connector_type_);
+}
+inline void PortComponentAttributes::set_connector_type(::dmi::PortComponentAttributes_ConnectorType value) {
+  
+  connector_type_ = value;
+  // @@protoc_insertion_point(field_set:dmi.PortComponentAttributes.connector_type)
+}
+
+// .dmi.PortComponentAttributes.Speed speed = 2;
+inline void PortComponentAttributes::clear_speed() {
+  speed_ = 0;
+}
+inline ::dmi::PortComponentAttributes_Speed PortComponentAttributes::speed() const {
+  // @@protoc_insertion_point(field_get:dmi.PortComponentAttributes.speed)
+  return static_cast< ::dmi::PortComponentAttributes_Speed >(speed_);
+}
+inline void PortComponentAttributes::set_speed(::dmi::PortComponentAttributes_Speed value) {
+  
+  speed_ = value;
+  // @@protoc_insertion_point(field_set:dmi.PortComponentAttributes.speed)
+}
+
+// .dmi.PortComponentAttributes.Protocol protocol = 3;
+inline void PortComponentAttributes::clear_protocol() {
+  protocol_ = 0;
+}
+inline ::dmi::PortComponentAttributes_Protocol PortComponentAttributes::protocol() const {
+  // @@protoc_insertion_point(field_get:dmi.PortComponentAttributes.protocol)
+  return static_cast< ::dmi::PortComponentAttributes_Protocol >(protocol_);
+}
+inline void PortComponentAttributes::set_protocol(::dmi::PortComponentAttributes_Protocol value) {
+  
+  protocol_ = value;
+  // @@protoc_insertion_point(field_set:dmi.PortComponentAttributes.protocol)
+}
+
+// string physical_label = 4;
+inline void PortComponentAttributes::clear_physical_label() {
+  physical_label_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& PortComponentAttributes::physical_label() const {
+  // @@protoc_insertion_point(field_get:dmi.PortComponentAttributes.physical_label)
+  return physical_label_.GetNoArena();
+}
+inline void PortComponentAttributes::set_physical_label(const ::std::string& value) {
+  
+  physical_label_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.PortComponentAttributes.physical_label)
+}
+#if LANG_CXX11
+inline void PortComponentAttributes::set_physical_label(::std::string&& value) {
+  
+  physical_label_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.PortComponentAttributes.physical_label)
+}
+#endif
+inline void PortComponentAttributes::set_physical_label(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  physical_label_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.PortComponentAttributes.physical_label)
+}
+inline void PortComponentAttributes::set_physical_label(const char* value, size_t size) {
+  
+  physical_label_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.PortComponentAttributes.physical_label)
+}
+inline ::std::string* PortComponentAttributes::mutable_physical_label() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.PortComponentAttributes.physical_label)
+  return physical_label_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* PortComponentAttributes::release_physical_label() {
+  // @@protoc_insertion_point(field_release:dmi.PortComponentAttributes.physical_label)
+  
+  return physical_label_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void PortComponentAttributes::set_allocated_physical_label(::std::string* physical_label) {
+  if (physical_label != nullptr) {
+    
+  } else {
+    
+  }
+  physical_label_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), physical_label);
+  // @@protoc_insertion_point(field_set_allocated:dmi.PortComponentAttributes.physical_label)
+}
+
+// -------------------------------------------------------------------
+
+// ContainerComponentAttributes
+
+// string physical_label = 1;
+inline void ContainerComponentAttributes::clear_physical_label() {
+  physical_label_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ContainerComponentAttributes::physical_label() const {
+  // @@protoc_insertion_point(field_get:dmi.ContainerComponentAttributes.physical_label)
+  return physical_label_.GetNoArena();
+}
+inline void ContainerComponentAttributes::set_physical_label(const ::std::string& value) {
+  
+  physical_label_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ContainerComponentAttributes.physical_label)
+}
+#if LANG_CXX11
+inline void ContainerComponentAttributes::set_physical_label(::std::string&& value) {
+  
+  physical_label_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ContainerComponentAttributes.physical_label)
+}
+#endif
+inline void ContainerComponentAttributes::set_physical_label(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  physical_label_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ContainerComponentAttributes.physical_label)
+}
+inline void ContainerComponentAttributes::set_physical_label(const char* value, size_t size) {
+  
+  physical_label_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ContainerComponentAttributes.physical_label)
+}
+inline ::std::string* ContainerComponentAttributes::mutable_physical_label() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ContainerComponentAttributes.physical_label)
+  return physical_label_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ContainerComponentAttributes::release_physical_label() {
+  // @@protoc_insertion_point(field_release:dmi.ContainerComponentAttributes.physical_label)
+  
+  return physical_label_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ContainerComponentAttributes::set_allocated_physical_label(::std::string* physical_label) {
+  if (physical_label != nullptr) {
+    
+  } else {
+    
+  }
+  physical_label_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), physical_label);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ContainerComponentAttributes.physical_label)
+}
+
+// -------------------------------------------------------------------
+
+// PsuComponentAttributes
+
+// .dmi.PsuComponentAttributes.SupportedVoltage supported_voltage = 1;
+inline void PsuComponentAttributes::clear_supported_voltage() {
+  supported_voltage_ = 0;
+}
+inline ::dmi::PsuComponentAttributes_SupportedVoltage PsuComponentAttributes::supported_voltage() const {
+  // @@protoc_insertion_point(field_get:dmi.PsuComponentAttributes.supported_voltage)
+  return static_cast< ::dmi::PsuComponentAttributes_SupportedVoltage >(supported_voltage_);
+}
+inline void PsuComponentAttributes::set_supported_voltage(::dmi::PsuComponentAttributes_SupportedVoltage value) {
+  
+  supported_voltage_ = value;
+  // @@protoc_insertion_point(field_set:dmi.PsuComponentAttributes.supported_voltage)
+}
+
+// -------------------------------------------------------------------
+
+// TransceiverComponentsAttributes
+
+// .dmi.TransceiverComponentsAttributes.FormFactor form_factor = 1;
+inline void TransceiverComponentsAttributes::clear_form_factor() {
+  form_factor_ = 0;
+}
+inline ::dmi::TransceiverComponentsAttributes_FormFactor TransceiverComponentsAttributes::form_factor() const {
+  // @@protoc_insertion_point(field_get:dmi.TransceiverComponentsAttributes.form_factor)
+  return static_cast< ::dmi::TransceiverComponentsAttributes_FormFactor >(form_factor_);
+}
+inline void TransceiverComponentsAttributes::set_form_factor(::dmi::TransceiverComponentsAttributes_FormFactor value) {
+  
+  form_factor_ = value;
+  // @@protoc_insertion_point(field_set:dmi.TransceiverComponentsAttributes.form_factor)
+}
+
+// .dmi.TransceiverComponentsAttributes.Type trans_type = 2;
+inline void TransceiverComponentsAttributes::clear_trans_type() {
+  trans_type_ = 0;
+}
+inline ::dmi::TransceiverComponentsAttributes_Type TransceiverComponentsAttributes::trans_type() const {
+  // @@protoc_insertion_point(field_get:dmi.TransceiverComponentsAttributes.trans_type)
+  return static_cast< ::dmi::TransceiverComponentsAttributes_Type >(trans_type_);
+}
+inline void TransceiverComponentsAttributes::set_trans_type(::dmi::TransceiverComponentsAttributes_Type value) {
+  
+  trans_type_ = value;
+  // @@protoc_insertion_point(field_set:dmi.TransceiverComponentsAttributes.trans_type)
+}
+
+// uint32 max_distance = 3;
+inline void TransceiverComponentsAttributes::clear_max_distance() {
+  max_distance_ = 0u;
+}
+inline ::google::protobuf::uint32 TransceiverComponentsAttributes::max_distance() const {
+  // @@protoc_insertion_point(field_get:dmi.TransceiverComponentsAttributes.max_distance)
+  return max_distance_;
+}
+inline void TransceiverComponentsAttributes::set_max_distance(::google::protobuf::uint32 value) {
+  
+  max_distance_ = value;
+  // @@protoc_insertion_point(field_set:dmi.TransceiverComponentsAttributes.max_distance)
+}
+
+// .dmi.ValueScale max_distance_scale = 4;
+inline void TransceiverComponentsAttributes::clear_max_distance_scale() {
+  max_distance_scale_ = 0;
+}
+inline ::dmi::ValueScale TransceiverComponentsAttributes::max_distance_scale() const {
+  // @@protoc_insertion_point(field_get:dmi.TransceiverComponentsAttributes.max_distance_scale)
+  return static_cast< ::dmi::ValueScale >(max_distance_scale_);
+}
+inline void TransceiverComponentsAttributes::set_max_distance_scale(::dmi::ValueScale value) {
+  
+  max_distance_scale_ = value;
+  // @@protoc_insertion_point(field_set:dmi.TransceiverComponentsAttributes.max_distance_scale)
+}
+
+// repeated uint32 rx_wavelength = 5;
+inline int TransceiverComponentsAttributes::rx_wavelength_size() const {
+  return rx_wavelength_.size();
+}
+inline void TransceiverComponentsAttributes::clear_rx_wavelength() {
+  rx_wavelength_.Clear();
+}
+inline ::google::protobuf::uint32 TransceiverComponentsAttributes::rx_wavelength(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.TransceiverComponentsAttributes.rx_wavelength)
+  return rx_wavelength_.Get(index);
+}
+inline void TransceiverComponentsAttributes::set_rx_wavelength(int index, ::google::protobuf::uint32 value) {
+  rx_wavelength_.Set(index, value);
+  // @@protoc_insertion_point(field_set:dmi.TransceiverComponentsAttributes.rx_wavelength)
+}
+inline void TransceiverComponentsAttributes::add_rx_wavelength(::google::protobuf::uint32 value) {
+  rx_wavelength_.Add(value);
+  // @@protoc_insertion_point(field_add:dmi.TransceiverComponentsAttributes.rx_wavelength)
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >&
+TransceiverComponentsAttributes::rx_wavelength() const {
+  // @@protoc_insertion_point(field_list:dmi.TransceiverComponentsAttributes.rx_wavelength)
+  return rx_wavelength_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >*
+TransceiverComponentsAttributes::mutable_rx_wavelength() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.TransceiverComponentsAttributes.rx_wavelength)
+  return &rx_wavelength_;
+}
+
+// repeated uint32 tx_wavelength = 6;
+inline int TransceiverComponentsAttributes::tx_wavelength_size() const {
+  return tx_wavelength_.size();
+}
+inline void TransceiverComponentsAttributes::clear_tx_wavelength() {
+  tx_wavelength_.Clear();
+}
+inline ::google::protobuf::uint32 TransceiverComponentsAttributes::tx_wavelength(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.TransceiverComponentsAttributes.tx_wavelength)
+  return tx_wavelength_.Get(index);
+}
+inline void TransceiverComponentsAttributes::set_tx_wavelength(int index, ::google::protobuf::uint32 value) {
+  tx_wavelength_.Set(index, value);
+  // @@protoc_insertion_point(field_set:dmi.TransceiverComponentsAttributes.tx_wavelength)
+}
+inline void TransceiverComponentsAttributes::add_tx_wavelength(::google::protobuf::uint32 value) {
+  tx_wavelength_.Add(value);
+  // @@protoc_insertion_point(field_add:dmi.TransceiverComponentsAttributes.tx_wavelength)
+}
+inline const ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >&
+TransceiverComponentsAttributes::tx_wavelength() const {
+  // @@protoc_insertion_point(field_list:dmi.TransceiverComponentsAttributes.tx_wavelength)
+  return tx_wavelength_;
+}
+inline ::google::protobuf::RepeatedField< ::google::protobuf::uint32 >*
+TransceiverComponentsAttributes::mutable_tx_wavelength() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.TransceiverComponentsAttributes.tx_wavelength)
+  return &tx_wavelength_;
+}
+
+// .dmi.ValueScale wavelength_scale = 7;
+inline void TransceiverComponentsAttributes::clear_wavelength_scale() {
+  wavelength_scale_ = 0;
+}
+inline ::dmi::ValueScale TransceiverComponentsAttributes::wavelength_scale() const {
+  // @@protoc_insertion_point(field_get:dmi.TransceiverComponentsAttributes.wavelength_scale)
+  return static_cast< ::dmi::ValueScale >(wavelength_scale_);
+}
+inline void TransceiverComponentsAttributes::set_wavelength_scale(::dmi::ValueScale value) {
+  
+  wavelength_scale_ = value;
+  // @@protoc_insertion_point(field_set:dmi.TransceiverComponentsAttributes.wavelength_scale)
+}
+
+// -------------------------------------------------------------------
+
+// Component
+
+// string name = 1;
+inline void Component::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Component::name() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.name)
+  return name_.GetNoArena();
+}
+inline void Component::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Component.name)
+}
+#if LANG_CXX11
+inline void Component::set_name(::std::string&& value) {
+  
+  name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Component.name)
+}
+#endif
+inline void Component::set_name(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Component.name)
+}
+inline void Component::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Component.name)
+}
+inline ::std::string* Component::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Component.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Component::release_name() {
+  // @@protoc_insertion_point(field_release:dmi.Component.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Component::set_allocated_name(::std::string* name) {
+  if (name != nullptr) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.name)
+}
+
+// .dmi.ComponentType class = 2;
+inline void Component::clear_class_() {
+  class__ = 0;
+}
+inline ::dmi::ComponentType Component::class_() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.class)
+  return static_cast< ::dmi::ComponentType >(class__);
+}
+inline void Component::set_class_(::dmi::ComponentType value) {
+  
+  class__ = value;
+  // @@protoc_insertion_point(field_set:dmi.Component.class)
+}
+
+// string description = 3;
+inline void Component::clear_description() {
+  description_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Component::description() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.description)
+  return description_.GetNoArena();
+}
+inline void Component::set_description(const ::std::string& value) {
+  
+  description_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Component.description)
+}
+#if LANG_CXX11
+inline void Component::set_description(::std::string&& value) {
+  
+  description_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Component.description)
+}
+#endif
+inline void Component::set_description(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  description_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Component.description)
+}
+inline void Component::set_description(const char* value, size_t size) {
+  
+  description_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Component.description)
+}
+inline ::std::string* Component::mutable_description() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Component.description)
+  return description_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Component::release_description() {
+  // @@protoc_insertion_point(field_release:dmi.Component.description)
+  
+  return description_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Component::set_allocated_description(::std::string* description) {
+  if (description != nullptr) {
+    
+  } else {
+    
+  }
+  description_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), description);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.description)
+}
+
+// string parent = 4;
+inline void Component::clear_parent() {
+  parent_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Component::parent() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.parent)
+  return parent_.GetNoArena();
+}
+inline void Component::set_parent(const ::std::string& value) {
+  
+  parent_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Component.parent)
+}
+#if LANG_CXX11
+inline void Component::set_parent(::std::string&& value) {
+  
+  parent_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Component.parent)
+}
+#endif
+inline void Component::set_parent(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  parent_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Component.parent)
+}
+inline void Component::set_parent(const char* value, size_t size) {
+  
+  parent_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Component.parent)
+}
+inline ::std::string* Component::mutable_parent() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Component.parent)
+  return parent_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Component::release_parent() {
+  // @@protoc_insertion_point(field_release:dmi.Component.parent)
+  
+  return parent_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Component::set_allocated_parent(::std::string* parent) {
+  if (parent != nullptr) {
+    
+  } else {
+    
+  }
+  parent_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parent);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.parent)
+}
+
+// int32 parent_rel_pos = 5;
+inline void Component::clear_parent_rel_pos() {
+  parent_rel_pos_ = 0;
+}
+inline ::google::protobuf::int32 Component::parent_rel_pos() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.parent_rel_pos)
+  return parent_rel_pos_;
+}
+inline void Component::set_parent_rel_pos(::google::protobuf::int32 value) {
+  
+  parent_rel_pos_ = value;
+  // @@protoc_insertion_point(field_set:dmi.Component.parent_rel_pos)
+}
+
+// repeated .dmi.Component children = 6;
+inline int Component::children_size() const {
+  return children_.size();
+}
+inline void Component::clear_children() {
+  children_.Clear();
+}
+inline ::dmi::Component* Component::mutable_children(int index) {
+  // @@protoc_insertion_point(field_mutable:dmi.Component.children)
+  return children_.Mutable(index);
+}
+inline ::google::protobuf::RepeatedPtrField< ::dmi::Component >*
+Component::mutable_children() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.Component.children)
+  return &children_;
+}
+inline const ::dmi::Component& Component::children(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.Component.children)
+  return children_.Get(index);
+}
+inline ::dmi::Component* Component::add_children() {
+  // @@protoc_insertion_point(field_add:dmi.Component.children)
+  return children_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::dmi::Component >&
+Component::children() const {
+  // @@protoc_insertion_point(field_list:dmi.Component.children)
+  return children_;
+}
+
+// string hardware_rev = 7;
+inline void Component::clear_hardware_rev() {
+  hardware_rev_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Component::hardware_rev() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.hardware_rev)
+  return hardware_rev_.GetNoArena();
+}
+inline void Component::set_hardware_rev(const ::std::string& value) {
+  
+  hardware_rev_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Component.hardware_rev)
+}
+#if LANG_CXX11
+inline void Component::set_hardware_rev(::std::string&& value) {
+  
+  hardware_rev_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Component.hardware_rev)
+}
+#endif
+inline void Component::set_hardware_rev(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  hardware_rev_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Component.hardware_rev)
+}
+inline void Component::set_hardware_rev(const char* value, size_t size) {
+  
+  hardware_rev_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Component.hardware_rev)
+}
+inline ::std::string* Component::mutable_hardware_rev() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Component.hardware_rev)
+  return hardware_rev_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Component::release_hardware_rev() {
+  // @@protoc_insertion_point(field_release:dmi.Component.hardware_rev)
+  
+  return hardware_rev_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Component::set_allocated_hardware_rev(::std::string* hardware_rev) {
+  if (hardware_rev != nullptr) {
+    
+  } else {
+    
+  }
+  hardware_rev_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), hardware_rev);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.hardware_rev)
+}
+
+// string firmware_rev = 8;
+inline void Component::clear_firmware_rev() {
+  firmware_rev_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Component::firmware_rev() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.firmware_rev)
+  return firmware_rev_.GetNoArena();
+}
+inline void Component::set_firmware_rev(const ::std::string& value) {
+  
+  firmware_rev_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Component.firmware_rev)
+}
+#if LANG_CXX11
+inline void Component::set_firmware_rev(::std::string&& value) {
+  
+  firmware_rev_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Component.firmware_rev)
+}
+#endif
+inline void Component::set_firmware_rev(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  firmware_rev_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Component.firmware_rev)
+}
+inline void Component::set_firmware_rev(const char* value, size_t size) {
+  
+  firmware_rev_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Component.firmware_rev)
+}
+inline ::std::string* Component::mutable_firmware_rev() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Component.firmware_rev)
+  return firmware_rev_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Component::release_firmware_rev() {
+  // @@protoc_insertion_point(field_release:dmi.Component.firmware_rev)
+  
+  return firmware_rev_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Component::set_allocated_firmware_rev(::std::string* firmware_rev) {
+  if (firmware_rev != nullptr) {
+    
+  } else {
+    
+  }
+  firmware_rev_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), firmware_rev);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.firmware_rev)
+}
+
+// string software_rev = 9;
+inline void Component::clear_software_rev() {
+  software_rev_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Component::software_rev() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.software_rev)
+  return software_rev_.GetNoArena();
+}
+inline void Component::set_software_rev(const ::std::string& value) {
+  
+  software_rev_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Component.software_rev)
+}
+#if LANG_CXX11
+inline void Component::set_software_rev(::std::string&& value) {
+  
+  software_rev_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Component.software_rev)
+}
+#endif
+inline void Component::set_software_rev(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  software_rev_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Component.software_rev)
+}
+inline void Component::set_software_rev(const char* value, size_t size) {
+  
+  software_rev_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Component.software_rev)
+}
+inline ::std::string* Component::mutable_software_rev() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Component.software_rev)
+  return software_rev_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Component::release_software_rev() {
+  // @@protoc_insertion_point(field_release:dmi.Component.software_rev)
+  
+  return software_rev_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Component::set_allocated_software_rev(::std::string* software_rev) {
+  if (software_rev != nullptr) {
+    
+  } else {
+    
+  }
+  software_rev_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), software_rev);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.software_rev)
+}
+
+// string serial_num = 10;
+inline void Component::clear_serial_num() {
+  serial_num_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Component::serial_num() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.serial_num)
+  return serial_num_.GetNoArena();
+}
+inline void Component::set_serial_num(const ::std::string& value) {
+  
+  serial_num_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Component.serial_num)
+}
+#if LANG_CXX11
+inline void Component::set_serial_num(::std::string&& value) {
+  
+  serial_num_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Component.serial_num)
+}
+#endif
+inline void Component::set_serial_num(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  serial_num_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Component.serial_num)
+}
+inline void Component::set_serial_num(const char* value, size_t size) {
+  
+  serial_num_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Component.serial_num)
+}
+inline ::std::string* Component::mutable_serial_num() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Component.serial_num)
+  return serial_num_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Component::release_serial_num() {
+  // @@protoc_insertion_point(field_release:dmi.Component.serial_num)
+  
+  return serial_num_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Component::set_allocated_serial_num(::std::string* serial_num) {
+  if (serial_num != nullptr) {
+    
+  } else {
+    
+  }
+  serial_num_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), serial_num);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.serial_num)
+}
+
+// string mfg_name = 11;
+inline void Component::clear_mfg_name() {
+  mfg_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Component::mfg_name() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.mfg_name)
+  return mfg_name_.GetNoArena();
+}
+inline void Component::set_mfg_name(const ::std::string& value) {
+  
+  mfg_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Component.mfg_name)
+}
+#if LANG_CXX11
+inline void Component::set_mfg_name(::std::string&& value) {
+  
+  mfg_name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Component.mfg_name)
+}
+#endif
+inline void Component::set_mfg_name(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  mfg_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Component.mfg_name)
+}
+inline void Component::set_mfg_name(const char* value, size_t size) {
+  
+  mfg_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Component.mfg_name)
+}
+inline ::std::string* Component::mutable_mfg_name() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Component.mfg_name)
+  return mfg_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Component::release_mfg_name() {
+  // @@protoc_insertion_point(field_release:dmi.Component.mfg_name)
+  
+  return mfg_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Component::set_allocated_mfg_name(::std::string* mfg_name) {
+  if (mfg_name != nullptr) {
+    
+  } else {
+    
+  }
+  mfg_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), mfg_name);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.mfg_name)
+}
+
+// string model_name = 12;
+inline void Component::clear_model_name() {
+  model_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Component::model_name() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.model_name)
+  return model_name_.GetNoArena();
+}
+inline void Component::set_model_name(const ::std::string& value) {
+  
+  model_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Component.model_name)
+}
+#if LANG_CXX11
+inline void Component::set_model_name(::std::string&& value) {
+  
+  model_name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Component.model_name)
+}
+#endif
+inline void Component::set_model_name(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  model_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Component.model_name)
+}
+inline void Component::set_model_name(const char* value, size_t size) {
+  
+  model_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Component.model_name)
+}
+inline ::std::string* Component::mutable_model_name() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Component.model_name)
+  return model_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Component::release_model_name() {
+  // @@protoc_insertion_point(field_release:dmi.Component.model_name)
+  
+  return model_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Component::set_allocated_model_name(::std::string* model_name) {
+  if (model_name != nullptr) {
+    
+  } else {
+    
+  }
+  model_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), model_name);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.model_name)
+}
+
+// string alias = 13;
+inline void Component::clear_alias() {
+  alias_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Component::alias() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.alias)
+  return alias_.GetNoArena();
+}
+inline void Component::set_alias(const ::std::string& value) {
+  
+  alias_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Component.alias)
+}
+#if LANG_CXX11
+inline void Component::set_alias(::std::string&& value) {
+  
+  alias_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Component.alias)
+}
+#endif
+inline void Component::set_alias(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  alias_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Component.alias)
+}
+inline void Component::set_alias(const char* value, size_t size) {
+  
+  alias_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Component.alias)
+}
+inline ::std::string* Component::mutable_alias() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Component.alias)
+  return alias_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Component::release_alias() {
+  // @@protoc_insertion_point(field_release:dmi.Component.alias)
+  
+  return alias_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Component::set_allocated_alias(::std::string* alias) {
+  if (alias != nullptr) {
+    
+  } else {
+    
+  }
+  alias_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), alias);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.alias)
+}
+
+// string asset_id = 14;
+inline void Component::clear_asset_id() {
+  asset_id_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Component::asset_id() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.asset_id)
+  return asset_id_.GetNoArena();
+}
+inline void Component::set_asset_id(const ::std::string& value) {
+  
+  asset_id_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Component.asset_id)
+}
+#if LANG_CXX11
+inline void Component::set_asset_id(::std::string&& value) {
+  
+  asset_id_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Component.asset_id)
+}
+#endif
+inline void Component::set_asset_id(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  asset_id_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Component.asset_id)
+}
+inline void Component::set_asset_id(const char* value, size_t size) {
+  
+  asset_id_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Component.asset_id)
+}
+inline ::std::string* Component::mutable_asset_id() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Component.asset_id)
+  return asset_id_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Component::release_asset_id() {
+  // @@protoc_insertion_point(field_release:dmi.Component.asset_id)
+  
+  return asset_id_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Component::set_allocated_asset_id(::std::string* asset_id) {
+  if (asset_id != nullptr) {
+    
+  } else {
+    
+  }
+  asset_id_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), asset_id);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.asset_id)
+}
+
+// bool is_fru = 15;
+inline void Component::clear_is_fru() {
+  is_fru_ = false;
+}
+inline bool Component::is_fru() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.is_fru)
+  return is_fru_;
+}
+inline void Component::set_is_fru(bool value) {
+  
+  is_fru_ = value;
+  // @@protoc_insertion_point(field_set:dmi.Component.is_fru)
+}
+
+// .google.protobuf.Timestamp mfg_date = 16;
+inline bool Component::has_mfg_date() const {
+  return this != internal_default_instance() && mfg_date_ != nullptr;
+}
+inline const ::google::protobuf::Timestamp& Component::mfg_date() const {
+  const ::google::protobuf::Timestamp* p = mfg_date_;
+  // @@protoc_insertion_point(field_get:dmi.Component.mfg_date)
+  return p != nullptr ? *p : *reinterpret_cast<const ::google::protobuf::Timestamp*>(
+      &::google::protobuf::_Timestamp_default_instance_);
+}
+inline ::google::protobuf::Timestamp* Component::release_mfg_date() {
+  // @@protoc_insertion_point(field_release:dmi.Component.mfg_date)
+  
+  ::google::protobuf::Timestamp* temp = mfg_date_;
+  mfg_date_ = nullptr;
+  return temp;
+}
+inline ::google::protobuf::Timestamp* Component::mutable_mfg_date() {
+  
+  if (mfg_date_ == nullptr) {
+    auto* p = CreateMaybeMessage<::google::protobuf::Timestamp>(GetArenaNoVirtual());
+    mfg_date_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Component.mfg_date)
+  return mfg_date_;
+}
+inline void Component::set_allocated_mfg_date(::google::protobuf::Timestamp* mfg_date) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(mfg_date_);
+  }
+  if (mfg_date) {
+    ::google::protobuf::Arena* submessage_arena =
+      reinterpret_cast<::google::protobuf::MessageLite*>(mfg_date)->GetArena();
+    if (message_arena != submessage_arena) {
+      mfg_date = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, mfg_date, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  mfg_date_ = mfg_date;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.mfg_date)
+}
+
+// .dmi.Uri uri = 17;
+inline bool Component::has_uri() const {
+  return this != internal_default_instance() && uri_ != nullptr;
+}
+inline void Component::clear_uri() {
+  if (GetArenaNoVirtual() == nullptr && uri_ != nullptr) {
+    delete uri_;
+  }
+  uri_ = nullptr;
+}
+inline const ::dmi::Uri& Component::uri() const {
+  const ::dmi::Uri* p = uri_;
+  // @@protoc_insertion_point(field_get:dmi.Component.uri)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uri*>(
+      &::dmi::_Uri_default_instance_);
+}
+inline ::dmi::Uri* Component::release_uri() {
+  // @@protoc_insertion_point(field_release:dmi.Component.uri)
+  
+  ::dmi::Uri* temp = uri_;
+  uri_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uri* Component::mutable_uri() {
+  
+  if (uri_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uri>(GetArenaNoVirtual());
+    uri_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Component.uri)
+  return uri_;
+}
+inline void Component::set_allocated_uri(::dmi::Uri* uri) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete uri_;
+  }
+  if (uri) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      uri = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, uri, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  uri_ = uri;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.uri)
+}
+
+// .dmi.Uuid uuid = 18;
+inline bool Component::has_uuid() const {
+  return this != internal_default_instance() && uuid_ != nullptr;
+}
+inline void Component::clear_uuid() {
+  if (GetArenaNoVirtual() == nullptr && uuid_ != nullptr) {
+    delete uuid_;
+  }
+  uuid_ = nullptr;
+}
+inline const ::dmi::Uuid& Component::uuid() const {
+  const ::dmi::Uuid* p = uuid_;
+  // @@protoc_insertion_point(field_get:dmi.Component.uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* Component::release_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.Component.uuid)
+  
+  ::dmi::Uuid* temp = uuid_;
+  uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* Component::mutable_uuid() {
+  
+  if (uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Component.uuid)
+  return uuid_;
+}
+inline void Component::set_allocated_uuid(::dmi::Uuid* uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete uuid_;
+  }
+  if (uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  uuid_ = uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.uuid)
+}
+
+// .dmi.ComponentState state = 19;
+inline bool Component::has_state() const {
+  return this != internal_default_instance() && state_ != nullptr;
+}
+inline void Component::clear_state() {
+  if (GetArenaNoVirtual() == nullptr && state_ != nullptr) {
+    delete state_;
+  }
+  state_ = nullptr;
+}
+inline const ::dmi::ComponentState& Component::state() const {
+  const ::dmi::ComponentState* p = state_;
+  // @@protoc_insertion_point(field_get:dmi.Component.state)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ComponentState*>(
+      &::dmi::_ComponentState_default_instance_);
+}
+inline ::dmi::ComponentState* Component::release_state() {
+  // @@protoc_insertion_point(field_release:dmi.Component.state)
+  
+  ::dmi::ComponentState* temp = state_;
+  state_ = nullptr;
+  return temp;
+}
+inline ::dmi::ComponentState* Component::mutable_state() {
+  
+  if (state_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ComponentState>(GetArenaNoVirtual());
+    state_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Component.state)
+  return state_;
+}
+inline void Component::set_allocated_state(::dmi::ComponentState* state) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete state_;
+  }
+  if (state) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      state = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, state, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  state_ = state;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Component.state)
+}
+
+// repeated .dmi.ComponentSensorData sensor_data = 20;
+inline int Component::sensor_data_size() const {
+  return sensor_data_.size();
+}
+inline void Component::clear_sensor_data() {
+  sensor_data_.Clear();
+}
+inline ::dmi::ComponentSensorData* Component::mutable_sensor_data(int index) {
+  // @@protoc_insertion_point(field_mutable:dmi.Component.sensor_data)
+  return sensor_data_.Mutable(index);
+}
+inline ::google::protobuf::RepeatedPtrField< ::dmi::ComponentSensorData >*
+Component::mutable_sensor_data() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.Component.sensor_data)
+  return &sensor_data_;
+}
+inline const ::dmi::ComponentSensorData& Component::sensor_data(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.Component.sensor_data)
+  return sensor_data_.Get(index);
+}
+inline ::dmi::ComponentSensorData* Component::add_sensor_data() {
+  // @@protoc_insertion_point(field_add:dmi.Component.sensor_data)
+  return sensor_data_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::dmi::ComponentSensorData >&
+Component::sensor_data() const {
+  // @@protoc_insertion_point(field_list:dmi.Component.sensor_data)
+  return sensor_data_;
+}
+
+// .dmi.PortComponentAttributes port_attr = 50;
+inline bool Component::has_port_attr() const {
+  return specific_case() == kPortAttr;
+}
+inline void Component::set_has_port_attr() {
+  _oneof_case_[0] = kPortAttr;
+}
+inline void Component::clear_port_attr() {
+  if (has_port_attr()) {
+    delete specific_.port_attr_;
+    clear_has_specific();
+  }
+}
+inline ::dmi::PortComponentAttributes* Component::release_port_attr() {
+  // @@protoc_insertion_point(field_release:dmi.Component.port_attr)
+  if (has_port_attr()) {
+    clear_has_specific();
+      ::dmi::PortComponentAttributes* temp = specific_.port_attr_;
+    specific_.port_attr_ = nullptr;
+    return temp;
+  } else {
+    return nullptr;
+  }
+}
+inline const ::dmi::PortComponentAttributes& Component::port_attr() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.port_attr)
+  return has_port_attr()
+      ? *specific_.port_attr_
+      : *reinterpret_cast< ::dmi::PortComponentAttributes*>(&::dmi::_PortComponentAttributes_default_instance_);
+}
+inline ::dmi::PortComponentAttributes* Component::mutable_port_attr() {
+  if (!has_port_attr()) {
+    clear_specific();
+    set_has_port_attr();
+    specific_.port_attr_ = CreateMaybeMessage< ::dmi::PortComponentAttributes >(
+        GetArenaNoVirtual());
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Component.port_attr)
+  return specific_.port_attr_;
+}
+
+// .dmi.ContainerComponentAttributes container_attr = 51;
+inline bool Component::has_container_attr() const {
+  return specific_case() == kContainerAttr;
+}
+inline void Component::set_has_container_attr() {
+  _oneof_case_[0] = kContainerAttr;
+}
+inline void Component::clear_container_attr() {
+  if (has_container_attr()) {
+    delete specific_.container_attr_;
+    clear_has_specific();
+  }
+}
+inline ::dmi::ContainerComponentAttributes* Component::release_container_attr() {
+  // @@protoc_insertion_point(field_release:dmi.Component.container_attr)
+  if (has_container_attr()) {
+    clear_has_specific();
+      ::dmi::ContainerComponentAttributes* temp = specific_.container_attr_;
+    specific_.container_attr_ = nullptr;
+    return temp;
+  } else {
+    return nullptr;
+  }
+}
+inline const ::dmi::ContainerComponentAttributes& Component::container_attr() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.container_attr)
+  return has_container_attr()
+      ? *specific_.container_attr_
+      : *reinterpret_cast< ::dmi::ContainerComponentAttributes*>(&::dmi::_ContainerComponentAttributes_default_instance_);
+}
+inline ::dmi::ContainerComponentAttributes* Component::mutable_container_attr() {
+  if (!has_container_attr()) {
+    clear_specific();
+    set_has_container_attr();
+    specific_.container_attr_ = CreateMaybeMessage< ::dmi::ContainerComponentAttributes >(
+        GetArenaNoVirtual());
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Component.container_attr)
+  return specific_.container_attr_;
+}
+
+// .dmi.PsuComponentAttributes psu_attr = 52;
+inline bool Component::has_psu_attr() const {
+  return specific_case() == kPsuAttr;
+}
+inline void Component::set_has_psu_attr() {
+  _oneof_case_[0] = kPsuAttr;
+}
+inline void Component::clear_psu_attr() {
+  if (has_psu_attr()) {
+    delete specific_.psu_attr_;
+    clear_has_specific();
+  }
+}
+inline ::dmi::PsuComponentAttributes* Component::release_psu_attr() {
+  // @@protoc_insertion_point(field_release:dmi.Component.psu_attr)
+  if (has_psu_attr()) {
+    clear_has_specific();
+      ::dmi::PsuComponentAttributes* temp = specific_.psu_attr_;
+    specific_.psu_attr_ = nullptr;
+    return temp;
+  } else {
+    return nullptr;
+  }
+}
+inline const ::dmi::PsuComponentAttributes& Component::psu_attr() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.psu_attr)
+  return has_psu_attr()
+      ? *specific_.psu_attr_
+      : *reinterpret_cast< ::dmi::PsuComponentAttributes*>(&::dmi::_PsuComponentAttributes_default_instance_);
+}
+inline ::dmi::PsuComponentAttributes* Component::mutable_psu_attr() {
+  if (!has_psu_attr()) {
+    clear_specific();
+    set_has_psu_attr();
+    specific_.psu_attr_ = CreateMaybeMessage< ::dmi::PsuComponentAttributes >(
+        GetArenaNoVirtual());
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Component.psu_attr)
+  return specific_.psu_attr_;
+}
+
+// .dmi.TransceiverComponentsAttributes transceiver_attr = 53;
+inline bool Component::has_transceiver_attr() const {
+  return specific_case() == kTransceiverAttr;
+}
+inline void Component::set_has_transceiver_attr() {
+  _oneof_case_[0] = kTransceiverAttr;
+}
+inline void Component::clear_transceiver_attr() {
+  if (has_transceiver_attr()) {
+    delete specific_.transceiver_attr_;
+    clear_has_specific();
+  }
+}
+inline ::dmi::TransceiverComponentsAttributes* Component::release_transceiver_attr() {
+  // @@protoc_insertion_point(field_release:dmi.Component.transceiver_attr)
+  if (has_transceiver_attr()) {
+    clear_has_specific();
+      ::dmi::TransceiverComponentsAttributes* temp = specific_.transceiver_attr_;
+    specific_.transceiver_attr_ = nullptr;
+    return temp;
+  } else {
+    return nullptr;
+  }
+}
+inline const ::dmi::TransceiverComponentsAttributes& Component::transceiver_attr() const {
+  // @@protoc_insertion_point(field_get:dmi.Component.transceiver_attr)
+  return has_transceiver_attr()
+      ? *specific_.transceiver_attr_
+      : *reinterpret_cast< ::dmi::TransceiverComponentsAttributes*>(&::dmi::_TransceiverComponentsAttributes_default_instance_);
+}
+inline ::dmi::TransceiverComponentsAttributes* Component::mutable_transceiver_attr() {
+  if (!has_transceiver_attr()) {
+    clear_specific();
+    set_has_transceiver_attr();
+    specific_.transceiver_attr_ = CreateMaybeMessage< ::dmi::TransceiverComponentsAttributes >(
+        GetArenaNoVirtual());
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Component.transceiver_attr)
+  return specific_.transceiver_attr_;
+}
+
+inline bool Component::has_specific() const {
+  return specific_case() != SPECIFIC_NOT_SET;
+}
+inline void Component::clear_has_specific() {
+  _oneof_case_[0] = SPECIFIC_NOT_SET;
+}
+inline Component::SpecificCase Component::specific_case() const {
+  return Component::SpecificCase(_oneof_case_[0]);
+}
+// -------------------------------------------------------------------
+
+// Hardware
+
+// .google.protobuf.Timestamp last_change = 1;
+inline bool Hardware::has_last_change() const {
+  return this != internal_default_instance() && last_change_ != nullptr;
+}
+inline const ::google::protobuf::Timestamp& Hardware::last_change() const {
+  const ::google::protobuf::Timestamp* p = last_change_;
+  // @@protoc_insertion_point(field_get:dmi.Hardware.last_change)
+  return p != nullptr ? *p : *reinterpret_cast<const ::google::protobuf::Timestamp*>(
+      &::google::protobuf::_Timestamp_default_instance_);
+}
+inline ::google::protobuf::Timestamp* Hardware::release_last_change() {
+  // @@protoc_insertion_point(field_release:dmi.Hardware.last_change)
+  
+  ::google::protobuf::Timestamp* temp = last_change_;
+  last_change_ = nullptr;
+  return temp;
+}
+inline ::google::protobuf::Timestamp* Hardware::mutable_last_change() {
+  
+  if (last_change_ == nullptr) {
+    auto* p = CreateMaybeMessage<::google::protobuf::Timestamp>(GetArenaNoVirtual());
+    last_change_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Hardware.last_change)
+  return last_change_;
+}
+inline void Hardware::set_allocated_last_change(::google::protobuf::Timestamp* last_change) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(last_change_);
+  }
+  if (last_change) {
+    ::google::protobuf::Arena* submessage_arena =
+      reinterpret_cast<::google::protobuf::MessageLite*>(last_change)->GetArena();
+    if (message_arena != submessage_arena) {
+      last_change = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, last_change, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  last_change_ = last_change;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Hardware.last_change)
+}
+
+// .dmi.Component root = 2;
+inline bool Hardware::has_root() const {
+  return this != internal_default_instance() && root_ != nullptr;
+}
+inline void Hardware::clear_root() {
+  if (GetArenaNoVirtual() == nullptr && root_ != nullptr) {
+    delete root_;
+  }
+  root_ = nullptr;
+}
+inline const ::dmi::Component& Hardware::root() const {
+  const ::dmi::Component* p = root_;
+  // @@protoc_insertion_point(field_get:dmi.Hardware.root)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Component*>(
+      &::dmi::_Component_default_instance_);
+}
+inline ::dmi::Component* Hardware::release_root() {
+  // @@protoc_insertion_point(field_release:dmi.Hardware.root)
+  
+  ::dmi::Component* temp = root_;
+  root_ = nullptr;
+  return temp;
+}
+inline ::dmi::Component* Hardware::mutable_root() {
+  
+  if (root_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Component>(GetArenaNoVirtual());
+    root_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Hardware.root)
+  return root_;
+}
+inline void Hardware::set_allocated_root(::dmi::Component* root) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete root_;
+  }
+  if (root) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      root = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, root, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  root_ = root;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Hardware.root)
+}
+
+// .google.protobuf.Timestamp last_booted = 3;
+inline bool Hardware::has_last_booted() const {
+  return this != internal_default_instance() && last_booted_ != nullptr;
+}
+inline const ::google::protobuf::Timestamp& Hardware::last_booted() const {
+  const ::google::protobuf::Timestamp* p = last_booted_;
+  // @@protoc_insertion_point(field_get:dmi.Hardware.last_booted)
+  return p != nullptr ? *p : *reinterpret_cast<const ::google::protobuf::Timestamp*>(
+      &::google::protobuf::_Timestamp_default_instance_);
+}
+inline ::google::protobuf::Timestamp* Hardware::release_last_booted() {
+  // @@protoc_insertion_point(field_release:dmi.Hardware.last_booted)
+  
+  ::google::protobuf::Timestamp* temp = last_booted_;
+  last_booted_ = nullptr;
+  return temp;
+}
+inline ::google::protobuf::Timestamp* Hardware::mutable_last_booted() {
+  
+  if (last_booted_ == nullptr) {
+    auto* p = CreateMaybeMessage<::google::protobuf::Timestamp>(GetArenaNoVirtual());
+    last_booted_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Hardware.last_booted)
+  return last_booted_;
+}
+inline void Hardware::set_allocated_last_booted(::google::protobuf::Timestamp* last_booted) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(last_booted_);
+  }
+  if (last_booted) {
+    ::google::protobuf::Arena* submessage_arena =
+      reinterpret_cast<::google::protobuf::MessageLite*>(last_booted)->GetArena();
+    if (message_arena != submessage_arena) {
+      last_booted = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, last_booted, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  last_booted_ = last_booted;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Hardware.last_booted)
+}
+
+// -------------------------------------------------------------------
+
+// ModifiableComponent
+
+// string name = 1;
+inline void ModifiableComponent::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ModifiableComponent::name() const {
+  // @@protoc_insertion_point(field_get:dmi.ModifiableComponent.name)
+  return name_.GetNoArena();
+}
+inline void ModifiableComponent::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ModifiableComponent.name)
+}
+#if LANG_CXX11
+inline void ModifiableComponent::set_name(::std::string&& value) {
+  
+  name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ModifiableComponent.name)
+}
+#endif
+inline void ModifiableComponent::set_name(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ModifiableComponent.name)
+}
+inline void ModifiableComponent::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ModifiableComponent.name)
+}
+inline ::std::string* ModifiableComponent::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ModifiableComponent.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ModifiableComponent::release_name() {
+  // @@protoc_insertion_point(field_release:dmi.ModifiableComponent.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ModifiableComponent::set_allocated_name(::std::string* name) {
+  if (name != nullptr) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ModifiableComponent.name)
+}
+
+// .dmi.ComponentType class = 2;
+inline void ModifiableComponent::clear_class_() {
+  class__ = 0;
+}
+inline ::dmi::ComponentType ModifiableComponent::class_() const {
+  // @@protoc_insertion_point(field_get:dmi.ModifiableComponent.class)
+  return static_cast< ::dmi::ComponentType >(class__);
+}
+inline void ModifiableComponent::set_class_(::dmi::ComponentType value) {
+  
+  class__ = value;
+  // @@protoc_insertion_point(field_set:dmi.ModifiableComponent.class)
+}
+
+// .dmi.Component parent = 3;
+inline bool ModifiableComponent::has_parent() const {
+  return this != internal_default_instance() && parent_ != nullptr;
+}
+inline void ModifiableComponent::clear_parent() {
+  if (GetArenaNoVirtual() == nullptr && parent_ != nullptr) {
+    delete parent_;
+  }
+  parent_ = nullptr;
+}
+inline const ::dmi::Component& ModifiableComponent::parent() const {
+  const ::dmi::Component* p = parent_;
+  // @@protoc_insertion_point(field_get:dmi.ModifiableComponent.parent)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Component*>(
+      &::dmi::_Component_default_instance_);
+}
+inline ::dmi::Component* ModifiableComponent::release_parent() {
+  // @@protoc_insertion_point(field_release:dmi.ModifiableComponent.parent)
+  
+  ::dmi::Component* temp = parent_;
+  parent_ = nullptr;
+  return temp;
+}
+inline ::dmi::Component* ModifiableComponent::mutable_parent() {
+  
+  if (parent_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Component>(GetArenaNoVirtual());
+    parent_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ModifiableComponent.parent)
+  return parent_;
+}
+inline void ModifiableComponent::set_allocated_parent(::dmi::Component* parent) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete parent_;
+  }
+  if (parent) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      parent = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, parent, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  parent_ = parent;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ModifiableComponent.parent)
+}
+
+// int32 parent_rel_pos = 4;
+inline void ModifiableComponent::clear_parent_rel_pos() {
+  parent_rel_pos_ = 0;
+}
+inline ::google::protobuf::int32 ModifiableComponent::parent_rel_pos() const {
+  // @@protoc_insertion_point(field_get:dmi.ModifiableComponent.parent_rel_pos)
+  return parent_rel_pos_;
+}
+inline void ModifiableComponent::set_parent_rel_pos(::google::protobuf::int32 value) {
+  
+  parent_rel_pos_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ModifiableComponent.parent_rel_pos)
+}
+
+// string alias = 5;
+inline void ModifiableComponent::clear_alias() {
+  alias_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ModifiableComponent::alias() const {
+  // @@protoc_insertion_point(field_get:dmi.ModifiableComponent.alias)
+  return alias_.GetNoArena();
+}
+inline void ModifiableComponent::set_alias(const ::std::string& value) {
+  
+  alias_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ModifiableComponent.alias)
+}
+#if LANG_CXX11
+inline void ModifiableComponent::set_alias(::std::string&& value) {
+  
+  alias_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ModifiableComponent.alias)
+}
+#endif
+inline void ModifiableComponent::set_alias(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  alias_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ModifiableComponent.alias)
+}
+inline void ModifiableComponent::set_alias(const char* value, size_t size) {
+  
+  alias_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ModifiableComponent.alias)
+}
+inline ::std::string* ModifiableComponent::mutable_alias() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ModifiableComponent.alias)
+  return alias_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ModifiableComponent::release_alias() {
+  // @@protoc_insertion_point(field_release:dmi.ModifiableComponent.alias)
+  
+  return alias_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ModifiableComponent::set_allocated_alias(::std::string* alias) {
+  if (alias != nullptr) {
+    
+  } else {
+    
+  }
+  alias_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), alias);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ModifiableComponent.alias)
+}
+
+// string asset_id = 6;
+inline void ModifiableComponent::clear_asset_id() {
+  asset_id_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ModifiableComponent::asset_id() const {
+  // @@protoc_insertion_point(field_get:dmi.ModifiableComponent.asset_id)
+  return asset_id_.GetNoArena();
+}
+inline void ModifiableComponent::set_asset_id(const ::std::string& value) {
+  
+  asset_id_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ModifiableComponent.asset_id)
+}
+#if LANG_CXX11
+inline void ModifiableComponent::set_asset_id(::std::string&& value) {
+  
+  asset_id_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ModifiableComponent.asset_id)
+}
+#endif
+inline void ModifiableComponent::set_asset_id(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  asset_id_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ModifiableComponent.asset_id)
+}
+inline void ModifiableComponent::set_asset_id(const char* value, size_t size) {
+  
+  asset_id_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ModifiableComponent.asset_id)
+}
+inline ::std::string* ModifiableComponent::mutable_asset_id() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ModifiableComponent.asset_id)
+  return asset_id_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ModifiableComponent::release_asset_id() {
+  // @@protoc_insertion_point(field_release:dmi.ModifiableComponent.asset_id)
+  
+  return asset_id_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ModifiableComponent::set_allocated_asset_id(::std::string* asset_id) {
+  if (asset_id != nullptr) {
+    
+  } else {
+    
+  }
+  asset_id_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), asset_id);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ModifiableComponent.asset_id)
+}
+
+// .dmi.Uri uri = 7;
+inline bool ModifiableComponent::has_uri() const {
+  return this != internal_default_instance() && uri_ != nullptr;
+}
+inline void ModifiableComponent::clear_uri() {
+  if (GetArenaNoVirtual() == nullptr && uri_ != nullptr) {
+    delete uri_;
+  }
+  uri_ = nullptr;
+}
+inline const ::dmi::Uri& ModifiableComponent::uri() const {
+  const ::dmi::Uri* p = uri_;
+  // @@protoc_insertion_point(field_get:dmi.ModifiableComponent.uri)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uri*>(
+      &::dmi::_Uri_default_instance_);
+}
+inline ::dmi::Uri* ModifiableComponent::release_uri() {
+  // @@protoc_insertion_point(field_release:dmi.ModifiableComponent.uri)
+  
+  ::dmi::Uri* temp = uri_;
+  uri_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uri* ModifiableComponent::mutable_uri() {
+  
+  if (uri_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uri>(GetArenaNoVirtual());
+    uri_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ModifiableComponent.uri)
+  return uri_;
+}
+inline void ModifiableComponent::set_allocated_uri(::dmi::Uri* uri) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete uri_;
+  }
+  if (uri) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      uri = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, uri, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  uri_ = uri;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ModifiableComponent.uri)
+}
+
+// .dmi.ComponentAdminState admin_state = 8;
+inline void ModifiableComponent::clear_admin_state() {
+  admin_state_ = 0;
+}
+inline ::dmi::ComponentAdminState ModifiableComponent::admin_state() const {
+  // @@protoc_insertion_point(field_get:dmi.ModifiableComponent.admin_state)
+  return static_cast< ::dmi::ComponentAdminState >(admin_state_);
+}
+inline void ModifiableComponent::set_admin_state(::dmi::ComponentAdminState value) {
+  
+  admin_state_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ModifiableComponent.admin_state)
+}
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace dmi
+
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::dmi::PortComponentAttributes_ConnectorType> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::PortComponentAttributes_ConnectorType>() {
+  return ::dmi::PortComponentAttributes_ConnectorType_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::PortComponentAttributes_Speed> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::PortComponentAttributes_Speed>() {
+  return ::dmi::PortComponentAttributes_Speed_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::PortComponentAttributes_Protocol> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::PortComponentAttributes_Protocol>() {
+  return ::dmi::PortComponentAttributes_Protocol_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::PsuComponentAttributes_SupportedVoltage> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::PsuComponentAttributes_SupportedVoltage>() {
+  return ::dmi::PsuComponentAttributes_SupportedVoltage_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::TransceiverComponentsAttributes_FormFactor> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::TransceiverComponentsAttributes_FormFactor>() {
+  return ::dmi::TransceiverComponentsAttributes_FormFactor_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::TransceiverComponentsAttributes_Type> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::TransceiverComponentsAttributes_Type>() {
+  return ::dmi::TransceiverComponentsAttributes_Type_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::ComponentType> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ComponentType>() {
+  return ::dmi::ComponentType_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::ComponentAdminState> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ComponentAdminState>() {
+  return ::dmi::ComponentAdminState_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::ComponentOperState> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ComponentOperState>() {
+  return ::dmi::ComponentOperState_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::ComponentUsageState> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ComponentUsageState>() {
+  return ::dmi::ComponentUsageState_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::ComponentAlarmState> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ComponentAlarmState>() {
+  return ::dmi::ComponentAlarmState_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::ComponentStandbyState> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ComponentStandbyState>() {
+  return ::dmi::ComponentStandbyState_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::DataValueType> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::DataValueType>() {
+  return ::dmi::DataValueType_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::ValueScale> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ValueScale>() {
+  return ::dmi::ValueScale_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::SensorStatus> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::SensorStatus>() {
+  return ::dmi::SensorStatus_descriptor();
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#include <google/protobuf/port_undef.inc>
+#endif  // PROTOBUF_INCLUDED_dmi_2fhw_2eproto
diff --git a/cpp/dmi/hw_events_mgmt_service.pb.cc b/cpp/dmi/hw_events_mgmt_service.pb.cc
new file mode 100644
index 0000000..4f856f0
--- /dev/null
+++ b/cpp/dmi/hw_events_mgmt_service.pb.cc
@@ -0,0 +1,5144 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/hw_events_mgmt_service.proto
+
+#include "dmi/hw_events_mgmt_service.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Uuid_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_ValueType_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_EventCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_EventMetaData_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_EventsCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_Thresholds_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_WaterMarks_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<2> scc_info_ThresholdInformation_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftimestamp_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto;
+namespace dmi {
+class ValueTypeDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ValueType> _instance;
+  ::google::protobuf::int64 int_val_;
+  ::google::protobuf::uint64 uint_val_;
+  float float_val_;
+} _ValueType_default_instance_;
+class WaterMarksDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<WaterMarks> _instance;
+} _WaterMarks_default_instance_;
+class ThresholdsDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Thresholds> _instance;
+  const ::dmi::WaterMarks* upper_;
+  const ::dmi::WaterMarks* lower_;
+} _Thresholds_default_instance_;
+class ThresholdInformationDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ThresholdInformation> _instance;
+} _ThresholdInformation_default_instance_;
+class EventCfgDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<EventCfg> _instance;
+} _EventCfg_default_instance_;
+class EventsCfgDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<EventsCfg> _instance;
+} _EventsCfg_default_instance_;
+class ListEventsResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ListEventsResponse> _instance;
+} _ListEventsResponse_default_instance_;
+class EventsConfigurationRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<EventsConfigurationRequest> _instance;
+  const ::dmi::EventsCfg* changes_;
+  bool reset_to_default_;
+} _EventsConfigurationRequest_default_instance_;
+class EventsConfigurationResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<EventsConfigurationResponse> _instance;
+} _EventsConfigurationResponse_default_instance_;
+class EventMetaDataDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<EventMetaData> _instance;
+} _EventMetaData_default_instance_;
+class EventDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Event> _instance;
+} _Event_default_instance_;
+}  // namespace dmi
+static void InitDefaultsValueType_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ValueType_default_instance_;
+    new (ptr) ::dmi::ValueType();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ValueType::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_ValueType_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsValueType_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto}, {}};
+
+static void InitDefaultsWaterMarks_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_WaterMarks_default_instance_;
+    new (ptr) ::dmi::WaterMarks();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::WaterMarks::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_WaterMarks_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsWaterMarks_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto}, {
+      &scc_info_ValueType_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsThresholds_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_Thresholds_default_instance_;
+    new (ptr) ::dmi::Thresholds();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::Thresholds::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_Thresholds_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsThresholds_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto}, {
+      &scc_info_WaterMarks_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsThresholdInformation_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ThresholdInformation_default_instance_;
+    new (ptr) ::dmi::ThresholdInformation();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ThresholdInformation::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_ThresholdInformation_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsThresholdInformation_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto}, {
+      &scc_info_ValueType_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base,
+      &scc_info_Thresholds_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsEventCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_EventCfg_default_instance_;
+    new (ptr) ::dmi::EventCfg();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::EventCfg::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_EventCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsEventCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto}, {
+      &scc_info_Thresholds_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsEventsCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_EventsCfg_default_instance_;
+    new (ptr) ::dmi::EventsCfg();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::EventsCfg::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_EventsCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsEventsCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto}, {
+      &scc_info_EventCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsListEventsResponse_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ListEventsResponse_default_instance_;
+    new (ptr) ::dmi::ListEventsResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ListEventsResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_ListEventsResponse_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsListEventsResponse_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto}, {
+      &scc_info_EventsCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsEventsConfigurationRequest_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_EventsConfigurationRequest_default_instance_;
+    new (ptr) ::dmi::EventsConfigurationRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::EventsConfigurationRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_EventsConfigurationRequest_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsEventsConfigurationRequest_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,
+      &scc_info_EventsCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsEventsConfigurationResponse_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_EventsConfigurationResponse_default_instance_;
+    new (ptr) ::dmi::EventsConfigurationResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::EventsConfigurationResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_EventsConfigurationResponse_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsEventsConfigurationResponse_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto}, {}};
+
+static void InitDefaultsEventMetaData_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_EventMetaData_default_instance_;
+    new (ptr) ::dmi::EventMetaData();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::EventMetaData::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_EventMetaData_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsEventMetaData_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsEvent_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_Event_default_instance_;
+    new (ptr) ::dmi::Event();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::Event::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<3> scc_info_Event_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 3, InitDefaultsEvent_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto}, {
+      &scc_info_EventMetaData_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base,
+      &scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto.base,
+      &scc_info_ThresholdInformation_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base,}};
+
+void InitDefaults_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  ::google::protobuf::internal::InitSCC(&scc_info_ValueType_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_WaterMarks_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_Thresholds_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ThresholdInformation_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_EventCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_EventsCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ListEventsResponse_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_EventsConfigurationRequest_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_EventsConfigurationResponse_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_EventMetaData_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_Event_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+}
+
+::google::protobuf::Metadata file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[11];
+const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[3];
+constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto = nullptr;
+
+const ::google::protobuf::uint32 TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ValueType, _internal_metadata_),
+  ~0u,  // no _extensions_
+  PROTOBUF_FIELD_OFFSET(::dmi::ValueType, _oneof_case_[0]),
+  ~0u,  // no _weak_field_map_
+  offsetof(::dmi::ValueTypeDefaultTypeInternal, int_val_),
+  offsetof(::dmi::ValueTypeDefaultTypeInternal, uint_val_),
+  offsetof(::dmi::ValueTypeDefaultTypeInternal, float_val_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ValueType, val_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::WaterMarks, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::WaterMarks, high_),
+  PROTOBUF_FIELD_OFFSET(::dmi::WaterMarks, low_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::Thresholds, _internal_metadata_),
+  ~0u,  // no _extensions_
+  PROTOBUF_FIELD_OFFSET(::dmi::Thresholds, _oneof_case_[0]),
+  ~0u,  // no _weak_field_map_
+  offsetof(::dmi::ThresholdsDefaultTypeInternal, upper_),
+  offsetof(::dmi::ThresholdsDefaultTypeInternal, lower_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Thresholds, threshold_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ThresholdInformation, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ThresholdInformation, observed_value_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ThresholdInformation, thresholds_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::EventCfg, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::EventCfg, event_id_),
+  PROTOBUF_FIELD_OFFSET(::dmi::EventCfg, is_configured_),
+  PROTOBUF_FIELD_OFFSET(::dmi::EventCfg, thresholds_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::EventsCfg, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::EventsCfg, items_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ListEventsResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ListEventsResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ListEventsResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ListEventsResponse, events_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ListEventsResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::EventsConfigurationRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  PROTOBUF_FIELD_OFFSET(::dmi::EventsConfigurationRequest, _oneof_case_[0]),
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::EventsConfigurationRequest, device_uuid_),
+  offsetof(::dmi::EventsConfigurationRequestDefaultTypeInternal, changes_),
+  offsetof(::dmi::EventsConfigurationRequestDefaultTypeInternal, reset_to_default_),
+  PROTOBUF_FIELD_OFFSET(::dmi::EventsConfigurationRequest, operation_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::EventsConfigurationResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::EventsConfigurationResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::EventsConfigurationResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::EventsConfigurationResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::EventMetaData, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::EventMetaData, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::EventMetaData, component_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::EventMetaData, component_name_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::Event, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::Event, event_metadata_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Event, event_id_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Event, raised_ts_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Event, threshold_info_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Event, add_info_),
+};
+static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, -1, sizeof(::dmi::ValueType)},
+  { 9, -1, sizeof(::dmi::WaterMarks)},
+  { 16, -1, sizeof(::dmi::Thresholds)},
+  { 24, -1, sizeof(::dmi::ThresholdInformation)},
+  { 31, -1, sizeof(::dmi::EventCfg)},
+  { 39, -1, sizeof(::dmi::EventsCfg)},
+  { 45, -1, sizeof(::dmi::ListEventsResponse)},
+  { 54, -1, sizeof(::dmi::EventsConfigurationRequest)},
+  { 63, -1, sizeof(::dmi::EventsConfigurationResponse)},
+  { 71, -1, sizeof(::dmi::EventMetaData)},
+  { 79, -1, sizeof(::dmi::Event)},
+};
+
+static ::google::protobuf::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ValueType_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_WaterMarks_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_Thresholds_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ThresholdInformation_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_EventCfg_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_EventsCfg_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ListEventsResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_EventsConfigurationRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_EventsConfigurationResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_EventMetaData_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_Event_default_instance_),
+};
+
+::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto = {
+  {}, AddDescriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto, "dmi/hw_events_mgmt_service.proto", schemas,
+  file_default_instances, TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto::offsets,
+  file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto, 11, file_level_enum_descriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto, file_level_service_descriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto,
+};
+
+const char descriptor_table_protodef_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[] =
+  "\n dmi/hw_events_mgmt_service.proto\022\003dmi\032"
+  "\021dmi/commons.proto\032\014dmi/hw.proto\032\037google"
+  "/protobuf/timestamp.proto\"N\n\tValueType\022\021"
+  "\n\007int_val\030\001 \001(\003H\000\022\022\n\010uint_val\030\002 \001(\004H\000\022\023\n"
+  "\tfloat_val\030\003 \001(\002H\000B\005\n\003val\"G\n\nWaterMarks\022"
+  "\034\n\004high\030\001 \001(\0132\016.dmi.ValueType\022\033\n\003low\030\002 \001"
+  "(\0132\016.dmi.ValueType\"]\n\nThresholds\022 \n\005uppe"
+  "r\030\001 \001(\0132\017.dmi.WaterMarksH\000\022 \n\005lower\030\002 \001("
+  "\0132\017.dmi.WaterMarksH\000B\013\n\tthreshold\"c\n\024Thr"
+  "esholdInformation\022&\n\016observed_value\030\001 \001("
+  "\0132\016.dmi.ValueType\022#\n\nthresholds\030\002 \001(\0132\017."
+  "dmi.Thresholds\"g\n\010EventCfg\022\037\n\010event_id\030\001"
+  " \001(\0162\r.dmi.EventIds\022\025\n\ris_configured\030\002 \001"
+  "(\010\022#\n\nthresholds\030\003 \001(\0132\017.dmi.Thresholds\""
+  ")\n\tEventsCfg\022\034\n\005items\030\001 \003(\0132\r.dmi.EventC"
+  "fg\"\370\001\n\022ListEventsResponse\022\033\n\006status\030\001 \001("
+  "\0162\013.dmi.Status\022.\n\006reason\030\002 \001(\0162\036.dmi.Lis"
+  "tEventsResponse.Reason\022\036\n\006events\030\003 \001(\0132\016"
+  ".dmi.EventsCfg\022\025\n\rreason_detail\030\004 \001(\t\"^\n"
+  "\006Reason\022\024\n\020UNDEFINED_REASON\020\000\022\022\n\016UNKNOWN"
+  "_DEVICE\020\001\022\022\n\016INTERNAL_ERROR\020\002\022\026\n\022DEVICE_"
+  "UNREACHABLE\020\003\"\210\001\n\032EventsConfigurationReq"
+  "uest\022\036\n\013device_uuid\030\001 \001(\0132\t.dmi.Uuid\022!\n\007"
+  "changes\030\002 \001(\0132\016.dmi.EventsCfgH\000\022\032\n\020reset"
+  "_to_default\030\003 \001(\010H\000B\013\n\toperation\"\376\001\n\033Eve"
+  "ntsConfigurationResponse\022\033\n\006status\030\001 \001(\016"
+  "2\013.dmi.Status\0227\n\006reason\030\002 \001(\0162\'.dmi.Even"
+  "tsConfigurationResponse.Reason\022\025\n\rreason"
+  "_detail\030\003 \001(\t\"r\n\006Reason\022\024\n\020UNDEFINED_REA"
+  "SON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERNAL_ER"
+  "ROR\020\002\022\022\n\016INVALID_CONFIG\020\003\022\026\n\022DEVICE_UNRE"
+  "ACHABLE\020\004\"j\n\rEventMetaData\022\036\n\013device_uui"
+  "d\030\001 \001(\0132\t.dmi.Uuid\022!\n\016component_uuid\030\002 \001"
+  "(\0132\t.dmi.Uuid\022\026\n\016component_name\030\003 \001(\t\"\310\001"
+  "\n\005Event\022*\n\016event_metadata\030\001 \001(\0132\022.dmi.Ev"
+  "entMetaData\022\037\n\010event_id\030\002 \001(\0162\r.dmi.Even"
+  "tIds\022-\n\traised_ts\030\003 \001(\0132\032.google.protobu"
+  "f.Timestamp\0221\n\016threshold_info\030\004 \001(\0132\031.dm"
+  "i.ThresholdInformation\022\020\n\010add_info\030\005 \001(\t"
+  "*\321\016\n\010EventIds\022\030\n\024EVENT_NAME_UNDEFINED\020\000\022"
+  "\036\n\032EVENT_TRANSCEIVER_PLUG_OUT\020d\022\035\n\031EVENT"
+  "_TRANSCEIVER_PLUG_IN\020e\022-\n)EVENT_TRANSCEI"
+  "VER_VOLTAGE_ABOVE_THRESHOLD\020f\022-\n)EVENT_T"
+  "RANSCEIVER_VOLTAGE_BELOW_THRESHOLD\020g\0221\n-"
+  "EVENT_TRANSCEIVER_TEMPERATURE_ABOVE_THRE"
+  "SHOLD\020h\0221\n-EVENT_TRANSCEIVER_TEMPERATURE"
+  "_BELOW_THRESHOLD\020i\022-\n)EVENT_TRANSCEIVER_"
+  "CURRENT_ABOVE_THRESHOLD\020j\022-\n)EVENT_TRANS"
+  "CEIVER_CURRENT_BELOW_THRESHOLD\020k\022.\n*EVEN"
+  "T_TRANSCEIVER_RX_POWER_ABOVE_THRESHOLD\020l"
+  "\022.\n*EVENT_TRANSCEIVER_RX_POWER_BELOW_THR"
+  "ESHOLD\020m\022.\n*EVENT_TRANSCEIVER_TX_POWER_A"
+  "BOVE_THRESHOLD\020n\022.\n*EVENT_TRANSCEIVER_TX"
+  "_POWER_BELOW_THRESHOLD\020o\022\035\n\031EVENT_TRANSC"
+  "EIVER_FAILURE\020p\0227\n3EVENT_TRANSCEIVER_VOL"
+  "TAGE_ABOVE_THRESHOLD_RECOVERED\020q\0227\n3EVEN"
+  "T_TRANSCEIVER_VOLTAGE_BELOW_THRESHOLD_RE"
+  "COVERED\020r\022;\n7EVENT_TRANSCEIVER_TEMPERATU"
+  "RE_ABOVE_THRESHOLD_RECOVERED\020s\022;\n7EVENT_"
+  "TRANSCEIVER_TEMPERATURE_BELOW_THRESHOLD_"
+  "RECOVERED\020t\0227\n3EVENT_TRANSCEIVER_CURRENT"
+  "_ABOVE_THRESHOLD_RECOVERED\020u\0227\n3EVENT_TR"
+  "ANSCEIVER_CURRENT_BELOW_THRESHOLD_RECOVE"
+  "RED\020v\0228\n4EVENT_TRANSCEIVER_RX_POWER_ABOV"
+  "E_THRESHOLD_RECOVERED\020w\0228\n4EVENT_TRANSCE"
+  "IVER_RX_POWER_BELOW_THRESHOLD_RECOVERED\020"
+  "x\0228\n4EVENT_TRANSCEIVER_TX_POWER_ABOVE_TH"
+  "RESHOLD_RECOVERED\020y\0228\n4EVENT_TRANSCEIVER"
+  "_TX_POWER_BELOW_THRESHOLD_RECOVERED\020z\022\'\n"
+  "#EVENT_TRANSCEIVER_FAILURE_RECOVERED\020{\022\027"
+  "\n\022EVENT_PSU_PLUG_OUT\020\310\001\022\026\n\021EVENT_PSU_PLU"
+  "G_IN\020\311\001\022\026\n\021EVENT_PSU_FAILURE\020\312\001\022 \n\033EVENT"
+  "_PSU_FAILURE_RECOVERED\020\313\001\022\026\n\021EVENT_FAN_F"
+  "AILURE\020\254\002\022\027\n\022EVENT_FAN_PLUG_OUT\020\255\002\022\026\n\021EV"
+  "ENT_FAN_PLUG_IN\020\256\002\022 \n\033EVENT_FAN_FAILURE_"
+  "RECOVERED\020\257\002\022)\n$EVENT_CPU_TEMPERATURE_AB"
+  "OVE_CRITICAL\020\220\003\022&\n!EVENT_CPU_TEMPERATURE"
+  "_ABOVE_FATAL\020\221\003\0223\n.EVENT_CPU_TEMPERATURE"
+  "_ABOVE_CRITICAL_RECOVERED\020\222\003\0220\n+EVENT_CP"
+  "U_TEMPERATURE_ABOVE_FATAL_RECOVERED\020\223\003\022\032"
+  "\n\025EVENT_HW_DEVICE_RESET\020\364\003\022/\n*EVENT_HW_D"
+  "EVICE_TEMPERATURE_ABOVE_CRITICAL\020\365\003\022,\n\'E"
+  "VENT_HW_DEVICE_TEMPERATURE_ABOVE_FATAL\020\366"
+  "\003\0229\n4EVENT_HW_DEVICE_TEMPERATURE_ABOVE_C"
+  "RITICAL_RECOVERED\020\367\003\0226\n1EVENT_HW_DEVICE_"
+  "TEMPERATURE_ABOVE_FATAL_RECOVERED\020\370\0032\267\001\n"
+  "\035NativeEventsManagementService\0226\n\nListEv"
+  "ents\022\017.dmi.HardwareID\032\027.dmi.ListEventsRe"
+  "sponse\022^\n\031UpdateEventsConfiguration\022\037.dm"
+  "i.EventsConfigurationRequest\032 .dmi.Event"
+  "sConfigurationResponseB;Z9github.com/ope"
+  "ncord/device-management-interface/v3/go/"
+  "dmib\006proto3"
+  ;
+::google::protobuf::internal::DescriptorTable descriptor_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto = {
+  false, InitDefaults_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto, 
+  descriptor_table_protodef_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto,
+  "dmi/hw_events_mgmt_service.proto", &assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto, 3691,
+};
+
+void AddDescriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
+  static constexpr ::google::protobuf::internal::InitFunc deps[3] =
+  {
+    ::AddDescriptors_dmi_2fcommons_2eproto,
+    ::AddDescriptors_dmi_2fhw_2eproto,
+    ::AddDescriptors_google_2fprotobuf_2ftimestamp_2eproto,
+  };
+ ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto, deps, 3);
+}
+
+// Force running AddDescriptors() at dynamic initialization time.
+static bool dynamic_init_dummy_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto = []() { AddDescriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto(); return true; }();
+namespace dmi {
+const ::google::protobuf::EnumDescriptor* ListEventsResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[0];
+}
+bool ListEventsResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const ListEventsResponse_Reason ListEventsResponse::UNDEFINED_REASON;
+const ListEventsResponse_Reason ListEventsResponse::UNKNOWN_DEVICE;
+const ListEventsResponse_Reason ListEventsResponse::INTERNAL_ERROR;
+const ListEventsResponse_Reason ListEventsResponse::DEVICE_UNREACHABLE;
+const ListEventsResponse_Reason ListEventsResponse::Reason_MIN;
+const ListEventsResponse_Reason ListEventsResponse::Reason_MAX;
+const int ListEventsResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* EventsConfigurationResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[1];
+}
+bool EventsConfigurationResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const EventsConfigurationResponse_Reason EventsConfigurationResponse::UNDEFINED_REASON;
+const EventsConfigurationResponse_Reason EventsConfigurationResponse::UNKNOWN_DEVICE;
+const EventsConfigurationResponse_Reason EventsConfigurationResponse::INTERNAL_ERROR;
+const EventsConfigurationResponse_Reason EventsConfigurationResponse::INVALID_CONFIG;
+const EventsConfigurationResponse_Reason EventsConfigurationResponse::DEVICE_UNREACHABLE;
+const EventsConfigurationResponse_Reason EventsConfigurationResponse::Reason_MIN;
+const EventsConfigurationResponse_Reason EventsConfigurationResponse::Reason_MAX;
+const int EventsConfigurationResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* EventIds_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[2];
+}
+bool EventIds_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 100:
+    case 101:
+    case 102:
+    case 103:
+    case 104:
+    case 105:
+    case 106:
+    case 107:
+    case 108:
+    case 109:
+    case 110:
+    case 111:
+    case 112:
+    case 113:
+    case 114:
+    case 115:
+    case 116:
+    case 117:
+    case 118:
+    case 119:
+    case 120:
+    case 121:
+    case 122:
+    case 123:
+    case 200:
+    case 201:
+    case 202:
+    case 203:
+    case 300:
+    case 301:
+    case 302:
+    case 303:
+    case 400:
+    case 401:
+    case 402:
+    case 403:
+    case 500:
+    case 501:
+    case 502:
+    case 503:
+    case 504:
+      return true;
+    default:
+      return false;
+  }
+}
+
+
+// ===================================================================
+
+void ValueType::InitAsDefaultInstance() {
+  ::dmi::_ValueType_default_instance_.int_val_ = PROTOBUF_LONGLONG(0);
+  ::dmi::_ValueType_default_instance_.uint_val_ = PROTOBUF_ULONGLONG(0);
+  ::dmi::_ValueType_default_instance_.float_val_ = 0;
+}
+class ValueType::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ValueType::kIntValFieldNumber;
+const int ValueType::kUintValFieldNumber;
+const int ValueType::kFloatValFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ValueType::ValueType()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ValueType)
+}
+ValueType::ValueType(const ValueType& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  clear_has_val();
+  switch (from.val_case()) {
+    case kIntVal: {
+      set_int_val(from.int_val());
+      break;
+    }
+    case kUintVal: {
+      set_uint_val(from.uint_val());
+      break;
+    }
+    case kFloatVal: {
+      set_float_val(from.float_val());
+      break;
+    }
+    case VAL_NOT_SET: {
+      break;
+    }
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.ValueType)
+}
+
+void ValueType::SharedCtor() {
+  clear_has_val();
+}
+
+ValueType::~ValueType() {
+  // @@protoc_insertion_point(destructor:dmi.ValueType)
+  SharedDtor();
+}
+
+void ValueType::SharedDtor() {
+  if (has_val()) {
+    clear_val();
+  }
+}
+
+void ValueType::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ValueType& ValueType::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ValueType_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ValueType::clear_val() {
+// @@protoc_insertion_point(one_of_clear_start:dmi.ValueType)
+  switch (val_case()) {
+    case kIntVal: {
+      // No need to clear
+      break;
+    }
+    case kUintVal: {
+      // No need to clear
+      break;
+    }
+    case kFloatVal: {
+      // No need to clear
+      break;
+    }
+    case VAL_NOT_SET: {
+      break;
+    }
+  }
+  _oneof_case_[0] = VAL_NOT_SET;
+}
+
+
+void ValueType::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ValueType)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  clear_val();
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ValueType::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ValueType*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // int64 int_val = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        msg->set_int_val(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // uint64 uint_val = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        msg->set_uint_val(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // float float_val = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 29) goto handle_unusual;
+        msg->set_float_val(::google::protobuf::io::UnalignedLoad<float>(ptr));
+        ptr += sizeof(float);
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ValueType::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ValueType)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // int64 int_val = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          clear_val();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
+                 input, &val_.int_val_)));
+          set_has_int_val();
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // uint64 uint_val = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          clear_val();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
+                 input, &val_.uint_val_)));
+          set_has_uint_val();
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // float float_val = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (29 & 0xFF)) {
+          clear_val();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
+                 input, &val_.float_val_)));
+          set_has_float_val();
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ValueType)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ValueType)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ValueType::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ValueType)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // int64 int_val = 1;
+  if (has_int_val()) {
+    ::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->int_val(), output);
+  }
+
+  // uint64 uint_val = 2;
+  if (has_uint_val()) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt64(2, this->uint_val(), output);
+  }
+
+  // float float_val = 3;
+  if (has_float_val()) {
+    ::google::protobuf::internal::WireFormatLite::WriteFloat(3, this->float_val(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ValueType)
+}
+
+::google::protobuf::uint8* ValueType::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ValueType)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // int64 int_val = 1;
+  if (has_int_val()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->int_val(), target);
+  }
+
+  // uint64 uint_val = 2;
+  if (has_uint_val()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(2, this->uint_val(), target);
+  }
+
+  // float float_val = 3;
+  if (has_float_val()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(3, this->float_val(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ValueType)
+  return target;
+}
+
+size_t ValueType::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ValueType)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  switch (val_case()) {
+    // int64 int_val = 1;
+    case kIntVal: {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::Int64Size(
+          this->int_val());
+      break;
+    }
+    // uint64 uint_val = 2;
+    case kUintVal: {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt64Size(
+          this->uint_val());
+      break;
+    }
+    // float float_val = 3;
+    case kFloatVal: {
+      total_size += 1 + 4;
+      break;
+    }
+    case VAL_NOT_SET: {
+      break;
+    }
+  }
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ValueType::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ValueType)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ValueType* source =
+      ::google::protobuf::DynamicCastToGenerated<ValueType>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ValueType)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ValueType)
+    MergeFrom(*source);
+  }
+}
+
+void ValueType::MergeFrom(const ValueType& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ValueType)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  switch (from.val_case()) {
+    case kIntVal: {
+      set_int_val(from.int_val());
+      break;
+    }
+    case kUintVal: {
+      set_uint_val(from.uint_val());
+      break;
+    }
+    case kFloatVal: {
+      set_float_val(from.float_val());
+      break;
+    }
+    case VAL_NOT_SET: {
+      break;
+    }
+  }
+}
+
+void ValueType::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ValueType)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ValueType::CopyFrom(const ValueType& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ValueType)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ValueType::IsInitialized() const {
+  return true;
+}
+
+void ValueType::Swap(ValueType* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ValueType::InternalSwap(ValueType* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(val_, other->val_);
+  swap(_oneof_case_[0], other->_oneof_case_[0]);
+}
+
+::google::protobuf::Metadata ValueType::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void WaterMarks::InitAsDefaultInstance() {
+  ::dmi::_WaterMarks_default_instance_._instance.get_mutable()->high_ = const_cast< ::dmi::ValueType*>(
+      ::dmi::ValueType::internal_default_instance());
+  ::dmi::_WaterMarks_default_instance_._instance.get_mutable()->low_ = const_cast< ::dmi::ValueType*>(
+      ::dmi::ValueType::internal_default_instance());
+}
+class WaterMarks::HasBitSetters {
+ public:
+  static const ::dmi::ValueType& high(const WaterMarks* msg);
+  static const ::dmi::ValueType& low(const WaterMarks* msg);
+};
+
+const ::dmi::ValueType&
+WaterMarks::HasBitSetters::high(const WaterMarks* msg) {
+  return *msg->high_;
+}
+const ::dmi::ValueType&
+WaterMarks::HasBitSetters::low(const WaterMarks* msg) {
+  return *msg->low_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int WaterMarks::kHighFieldNumber;
+const int WaterMarks::kLowFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+WaterMarks::WaterMarks()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.WaterMarks)
+}
+WaterMarks::WaterMarks(const WaterMarks& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_high()) {
+    high_ = new ::dmi::ValueType(*from.high_);
+  } else {
+    high_ = nullptr;
+  }
+  if (from.has_low()) {
+    low_ = new ::dmi::ValueType(*from.low_);
+  } else {
+    low_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.WaterMarks)
+}
+
+void WaterMarks::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_WaterMarks_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::memset(&high_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&low_) -
+      reinterpret_cast<char*>(&high_)) + sizeof(low_));
+}
+
+WaterMarks::~WaterMarks() {
+  // @@protoc_insertion_point(destructor:dmi.WaterMarks)
+  SharedDtor();
+}
+
+void WaterMarks::SharedDtor() {
+  if (this != internal_default_instance()) delete high_;
+  if (this != internal_default_instance()) delete low_;
+}
+
+void WaterMarks::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const WaterMarks& WaterMarks::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_WaterMarks_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void WaterMarks::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.WaterMarks)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && high_ != nullptr) {
+    delete high_;
+  }
+  high_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && low_ != nullptr) {
+    delete low_;
+  }
+  low_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* WaterMarks::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<WaterMarks*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.ValueType high = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::ValueType::_InternalParse;
+        object = msg->mutable_high();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.ValueType low = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::ValueType::_InternalParse;
+        object = msg->mutable_low();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool WaterMarks::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.WaterMarks)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.ValueType high = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_high()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ValueType low = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_low()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.WaterMarks)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.WaterMarks)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void WaterMarks::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.WaterMarks)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.ValueType high = 1;
+  if (this->has_high()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::high(this), output);
+  }
+
+  // .dmi.ValueType low = 2;
+  if (this->has_low()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::low(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.WaterMarks)
+}
+
+::google::protobuf::uint8* WaterMarks::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.WaterMarks)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.ValueType high = 1;
+  if (this->has_high()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::high(this), target);
+  }
+
+  // .dmi.ValueType low = 2;
+  if (this->has_low()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::low(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.WaterMarks)
+  return target;
+}
+
+size_t WaterMarks::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.WaterMarks)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.ValueType high = 1;
+  if (this->has_high()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *high_);
+  }
+
+  // .dmi.ValueType low = 2;
+  if (this->has_low()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *low_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void WaterMarks::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.WaterMarks)
+  GOOGLE_DCHECK_NE(&from, this);
+  const WaterMarks* source =
+      ::google::protobuf::DynamicCastToGenerated<WaterMarks>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.WaterMarks)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.WaterMarks)
+    MergeFrom(*source);
+  }
+}
+
+void WaterMarks::MergeFrom(const WaterMarks& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.WaterMarks)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_high()) {
+    mutable_high()->::dmi::ValueType::MergeFrom(from.high());
+  }
+  if (from.has_low()) {
+    mutable_low()->::dmi::ValueType::MergeFrom(from.low());
+  }
+}
+
+void WaterMarks::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.WaterMarks)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void WaterMarks::CopyFrom(const WaterMarks& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.WaterMarks)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool WaterMarks::IsInitialized() const {
+  return true;
+}
+
+void WaterMarks::Swap(WaterMarks* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void WaterMarks::InternalSwap(WaterMarks* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(high_, other->high_);
+  swap(low_, other->low_);
+}
+
+::google::protobuf::Metadata WaterMarks::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void Thresholds::InitAsDefaultInstance() {
+  ::dmi::_Thresholds_default_instance_.upper_ = const_cast< ::dmi::WaterMarks*>(
+      ::dmi::WaterMarks::internal_default_instance());
+  ::dmi::_Thresholds_default_instance_.lower_ = const_cast< ::dmi::WaterMarks*>(
+      ::dmi::WaterMarks::internal_default_instance());
+}
+class Thresholds::HasBitSetters {
+ public:
+  static const ::dmi::WaterMarks& upper(const Thresholds* msg);
+  static const ::dmi::WaterMarks& lower(const Thresholds* msg);
+};
+
+const ::dmi::WaterMarks&
+Thresholds::HasBitSetters::upper(const Thresholds* msg) {
+  return *msg->threshold_.upper_;
+}
+const ::dmi::WaterMarks&
+Thresholds::HasBitSetters::lower(const Thresholds* msg) {
+  return *msg->threshold_.lower_;
+}
+void Thresholds::set_allocated_upper(::dmi::WaterMarks* upper) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  clear_threshold();
+  if (upper) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      upper = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, upper, submessage_arena);
+    }
+    set_has_upper();
+    threshold_.upper_ = upper;
+  }
+  // @@protoc_insertion_point(field_set_allocated:dmi.Thresholds.upper)
+}
+void Thresholds::set_allocated_lower(::dmi::WaterMarks* lower) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  clear_threshold();
+  if (lower) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      lower = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, lower, submessage_arena);
+    }
+    set_has_lower();
+    threshold_.lower_ = lower;
+  }
+  // @@protoc_insertion_point(field_set_allocated:dmi.Thresholds.lower)
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Thresholds::kUpperFieldNumber;
+const int Thresholds::kLowerFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Thresholds::Thresholds()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.Thresholds)
+}
+Thresholds::Thresholds(const Thresholds& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  clear_has_threshold();
+  switch (from.threshold_case()) {
+    case kUpper: {
+      mutable_upper()->::dmi::WaterMarks::MergeFrom(from.upper());
+      break;
+    }
+    case kLower: {
+      mutable_lower()->::dmi::WaterMarks::MergeFrom(from.lower());
+      break;
+    }
+    case THRESHOLD_NOT_SET: {
+      break;
+    }
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.Thresholds)
+}
+
+void Thresholds::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_Thresholds_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  clear_has_threshold();
+}
+
+Thresholds::~Thresholds() {
+  // @@protoc_insertion_point(destructor:dmi.Thresholds)
+  SharedDtor();
+}
+
+void Thresholds::SharedDtor() {
+  if (has_threshold()) {
+    clear_threshold();
+  }
+}
+
+void Thresholds::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const Thresholds& Thresholds::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_Thresholds_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void Thresholds::clear_threshold() {
+// @@protoc_insertion_point(one_of_clear_start:dmi.Thresholds)
+  switch (threshold_case()) {
+    case kUpper: {
+      delete threshold_.upper_;
+      break;
+    }
+    case kLower: {
+      delete threshold_.lower_;
+      break;
+    }
+    case THRESHOLD_NOT_SET: {
+      break;
+    }
+  }
+  _oneof_case_[0] = THRESHOLD_NOT_SET;
+}
+
+
+void Thresholds::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.Thresholds)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  clear_threshold();
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* Thresholds::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<Thresholds*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.WaterMarks upper = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::WaterMarks::_InternalParse;
+        object = msg->mutable_upper();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.WaterMarks lower = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::WaterMarks::_InternalParse;
+        object = msg->mutable_lower();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool Thresholds::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.Thresholds)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.WaterMarks upper = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_upper()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.WaterMarks lower = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_lower()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.Thresholds)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.Thresholds)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void Thresholds::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.Thresholds)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.WaterMarks upper = 1;
+  if (has_upper()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::upper(this), output);
+  }
+
+  // .dmi.WaterMarks lower = 2;
+  if (has_lower()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::lower(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.Thresholds)
+}
+
+::google::protobuf::uint8* Thresholds::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.Thresholds)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.WaterMarks upper = 1;
+  if (has_upper()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::upper(this), target);
+  }
+
+  // .dmi.WaterMarks lower = 2;
+  if (has_lower()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::lower(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.Thresholds)
+  return target;
+}
+
+size_t Thresholds::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.Thresholds)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  switch (threshold_case()) {
+    // .dmi.WaterMarks upper = 1;
+    case kUpper: {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          *threshold_.upper_);
+      break;
+    }
+    // .dmi.WaterMarks lower = 2;
+    case kLower: {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          *threshold_.lower_);
+      break;
+    }
+    case THRESHOLD_NOT_SET: {
+      break;
+    }
+  }
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void Thresholds::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.Thresholds)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Thresholds* source =
+      ::google::protobuf::DynamicCastToGenerated<Thresholds>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.Thresholds)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.Thresholds)
+    MergeFrom(*source);
+  }
+}
+
+void Thresholds::MergeFrom(const Thresholds& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.Thresholds)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  switch (from.threshold_case()) {
+    case kUpper: {
+      mutable_upper()->::dmi::WaterMarks::MergeFrom(from.upper());
+      break;
+    }
+    case kLower: {
+      mutable_lower()->::dmi::WaterMarks::MergeFrom(from.lower());
+      break;
+    }
+    case THRESHOLD_NOT_SET: {
+      break;
+    }
+  }
+}
+
+void Thresholds::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.Thresholds)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Thresholds::CopyFrom(const Thresholds& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.Thresholds)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Thresholds::IsInitialized() const {
+  return true;
+}
+
+void Thresholds::Swap(Thresholds* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Thresholds::InternalSwap(Thresholds* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(threshold_, other->threshold_);
+  swap(_oneof_case_[0], other->_oneof_case_[0]);
+}
+
+::google::protobuf::Metadata Thresholds::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ThresholdInformation::InitAsDefaultInstance() {
+  ::dmi::_ThresholdInformation_default_instance_._instance.get_mutable()->observed_value_ = const_cast< ::dmi::ValueType*>(
+      ::dmi::ValueType::internal_default_instance());
+  ::dmi::_ThresholdInformation_default_instance_._instance.get_mutable()->thresholds_ = const_cast< ::dmi::Thresholds*>(
+      ::dmi::Thresholds::internal_default_instance());
+}
+class ThresholdInformation::HasBitSetters {
+ public:
+  static const ::dmi::ValueType& observed_value(const ThresholdInformation* msg);
+  static const ::dmi::Thresholds& thresholds(const ThresholdInformation* msg);
+};
+
+const ::dmi::ValueType&
+ThresholdInformation::HasBitSetters::observed_value(const ThresholdInformation* msg) {
+  return *msg->observed_value_;
+}
+const ::dmi::Thresholds&
+ThresholdInformation::HasBitSetters::thresholds(const ThresholdInformation* msg) {
+  return *msg->thresholds_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ThresholdInformation::kObservedValueFieldNumber;
+const int ThresholdInformation::kThresholdsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ThresholdInformation::ThresholdInformation()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ThresholdInformation)
+}
+ThresholdInformation::ThresholdInformation(const ThresholdInformation& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_observed_value()) {
+    observed_value_ = new ::dmi::ValueType(*from.observed_value_);
+  } else {
+    observed_value_ = nullptr;
+  }
+  if (from.has_thresholds()) {
+    thresholds_ = new ::dmi::Thresholds(*from.thresholds_);
+  } else {
+    thresholds_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.ThresholdInformation)
+}
+
+void ThresholdInformation::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ThresholdInformation_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::memset(&observed_value_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&thresholds_) -
+      reinterpret_cast<char*>(&observed_value_)) + sizeof(thresholds_));
+}
+
+ThresholdInformation::~ThresholdInformation() {
+  // @@protoc_insertion_point(destructor:dmi.ThresholdInformation)
+  SharedDtor();
+}
+
+void ThresholdInformation::SharedDtor() {
+  if (this != internal_default_instance()) delete observed_value_;
+  if (this != internal_default_instance()) delete thresholds_;
+}
+
+void ThresholdInformation::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ThresholdInformation& ThresholdInformation::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ThresholdInformation_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ThresholdInformation::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ThresholdInformation)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && observed_value_ != nullptr) {
+    delete observed_value_;
+  }
+  observed_value_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && thresholds_ != nullptr) {
+    delete thresholds_;
+  }
+  thresholds_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ThresholdInformation::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ThresholdInformation*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.ValueType observed_value = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::ValueType::_InternalParse;
+        object = msg->mutable_observed_value();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.Thresholds thresholds = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Thresholds::_InternalParse;
+        object = msg->mutable_thresholds();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ThresholdInformation::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ThresholdInformation)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.ValueType observed_value = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_observed_value()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Thresholds thresholds = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_thresholds()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ThresholdInformation)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ThresholdInformation)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ThresholdInformation::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ThresholdInformation)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.ValueType observed_value = 1;
+  if (this->has_observed_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::observed_value(this), output);
+  }
+
+  // .dmi.Thresholds thresholds = 2;
+  if (this->has_thresholds()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::thresholds(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ThresholdInformation)
+}
+
+::google::protobuf::uint8* ThresholdInformation::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ThresholdInformation)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.ValueType observed_value = 1;
+  if (this->has_observed_value()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::observed_value(this), target);
+  }
+
+  // .dmi.Thresholds thresholds = 2;
+  if (this->has_thresholds()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::thresholds(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ThresholdInformation)
+  return target;
+}
+
+size_t ThresholdInformation::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ThresholdInformation)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.ValueType observed_value = 1;
+  if (this->has_observed_value()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *observed_value_);
+  }
+
+  // .dmi.Thresholds thresholds = 2;
+  if (this->has_thresholds()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *thresholds_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ThresholdInformation::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ThresholdInformation)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ThresholdInformation* source =
+      ::google::protobuf::DynamicCastToGenerated<ThresholdInformation>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ThresholdInformation)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ThresholdInformation)
+    MergeFrom(*source);
+  }
+}
+
+void ThresholdInformation::MergeFrom(const ThresholdInformation& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ThresholdInformation)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_observed_value()) {
+    mutable_observed_value()->::dmi::ValueType::MergeFrom(from.observed_value());
+  }
+  if (from.has_thresholds()) {
+    mutable_thresholds()->::dmi::Thresholds::MergeFrom(from.thresholds());
+  }
+}
+
+void ThresholdInformation::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ThresholdInformation)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ThresholdInformation::CopyFrom(const ThresholdInformation& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ThresholdInformation)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ThresholdInformation::IsInitialized() const {
+  return true;
+}
+
+void ThresholdInformation::Swap(ThresholdInformation* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ThresholdInformation::InternalSwap(ThresholdInformation* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(observed_value_, other->observed_value_);
+  swap(thresholds_, other->thresholds_);
+}
+
+::google::protobuf::Metadata ThresholdInformation::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void EventCfg::InitAsDefaultInstance() {
+  ::dmi::_EventCfg_default_instance_._instance.get_mutable()->thresholds_ = const_cast< ::dmi::Thresholds*>(
+      ::dmi::Thresholds::internal_default_instance());
+}
+class EventCfg::HasBitSetters {
+ public:
+  static const ::dmi::Thresholds& thresholds(const EventCfg* msg);
+};
+
+const ::dmi::Thresholds&
+EventCfg::HasBitSetters::thresholds(const EventCfg* msg) {
+  return *msg->thresholds_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int EventCfg::kEventIdFieldNumber;
+const int EventCfg::kIsConfiguredFieldNumber;
+const int EventCfg::kThresholdsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+EventCfg::EventCfg()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.EventCfg)
+}
+EventCfg::EventCfg(const EventCfg& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_thresholds()) {
+    thresholds_ = new ::dmi::Thresholds(*from.thresholds_);
+  } else {
+    thresholds_ = nullptr;
+  }
+  ::memcpy(&event_id_, &from.event_id_,
+    static_cast<size_t>(reinterpret_cast<char*>(&is_configured_) -
+    reinterpret_cast<char*>(&event_id_)) + sizeof(is_configured_));
+  // @@protoc_insertion_point(copy_constructor:dmi.EventCfg)
+}
+
+void EventCfg::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_EventCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  ::memset(&thresholds_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&is_configured_) -
+      reinterpret_cast<char*>(&thresholds_)) + sizeof(is_configured_));
+}
+
+EventCfg::~EventCfg() {
+  // @@protoc_insertion_point(destructor:dmi.EventCfg)
+  SharedDtor();
+}
+
+void EventCfg::SharedDtor() {
+  if (this != internal_default_instance()) delete thresholds_;
+}
+
+void EventCfg::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const EventCfg& EventCfg::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_EventCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void EventCfg::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.EventCfg)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && thresholds_ != nullptr) {
+    delete thresholds_;
+  }
+  thresholds_ = nullptr;
+  ::memset(&event_id_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&is_configured_) -
+      reinterpret_cast<char*>(&event_id_)) + sizeof(is_configured_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* EventCfg::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<EventCfg*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.EventIds event_id = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_event_id(static_cast<::dmi::EventIds>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // bool is_configured = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        msg->set_is_configured(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.Thresholds thresholds = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Thresholds::_InternalParse;
+        object = msg->mutable_thresholds();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool EventCfg::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.EventCfg)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.EventIds event_id = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_event_id(static_cast< ::dmi::EventIds >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // bool is_configured = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &is_configured_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Thresholds thresholds = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_thresholds()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.EventCfg)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.EventCfg)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void EventCfg::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.EventCfg)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.EventIds event_id = 1;
+  if (this->event_id() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->event_id(), output);
+  }
+
+  // bool is_configured = 2;
+  if (this->is_configured() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_configured(), output);
+  }
+
+  // .dmi.Thresholds thresholds = 3;
+  if (this->has_thresholds()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::thresholds(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.EventCfg)
+}
+
+::google::protobuf::uint8* EventCfg::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.EventCfg)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.EventIds event_id = 1;
+  if (this->event_id() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->event_id(), target);
+  }
+
+  // bool is_configured = 2;
+  if (this->is_configured() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_configured(), target);
+  }
+
+  // .dmi.Thresholds thresholds = 3;
+  if (this->has_thresholds()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::thresholds(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.EventCfg)
+  return target;
+}
+
+size_t EventCfg::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.EventCfg)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.Thresholds thresholds = 3;
+  if (this->has_thresholds()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *thresholds_);
+  }
+
+  // .dmi.EventIds event_id = 1;
+  if (this->event_id() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->event_id());
+  }
+
+  // bool is_configured = 2;
+  if (this->is_configured() != 0) {
+    total_size += 1 + 1;
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void EventCfg::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.EventCfg)
+  GOOGLE_DCHECK_NE(&from, this);
+  const EventCfg* source =
+      ::google::protobuf::DynamicCastToGenerated<EventCfg>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.EventCfg)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.EventCfg)
+    MergeFrom(*source);
+  }
+}
+
+void EventCfg::MergeFrom(const EventCfg& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.EventCfg)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_thresholds()) {
+    mutable_thresholds()->::dmi::Thresholds::MergeFrom(from.thresholds());
+  }
+  if (from.event_id() != 0) {
+    set_event_id(from.event_id());
+  }
+  if (from.is_configured() != 0) {
+    set_is_configured(from.is_configured());
+  }
+}
+
+void EventCfg::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.EventCfg)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EventCfg::CopyFrom(const EventCfg& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.EventCfg)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool EventCfg::IsInitialized() const {
+  return true;
+}
+
+void EventCfg::Swap(EventCfg* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void EventCfg::InternalSwap(EventCfg* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(thresholds_, other->thresholds_);
+  swap(event_id_, other->event_id_);
+  swap(is_configured_, other->is_configured_);
+}
+
+::google::protobuf::Metadata EventCfg::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void EventsCfg::InitAsDefaultInstance() {
+}
+class EventsCfg::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int EventsCfg::kItemsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+EventsCfg::EventsCfg()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.EventsCfg)
+}
+EventsCfg::EventsCfg(const EventsCfg& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr),
+      items_(from.items_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  // @@protoc_insertion_point(copy_constructor:dmi.EventsCfg)
+}
+
+void EventsCfg::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_EventsCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+}
+
+EventsCfg::~EventsCfg() {
+  // @@protoc_insertion_point(destructor:dmi.EventsCfg)
+  SharedDtor();
+}
+
+void EventsCfg::SharedDtor() {
+}
+
+void EventsCfg::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const EventsCfg& EventsCfg::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_EventsCfg_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void EventsCfg::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.EventsCfg)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  items_.Clear();
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* EventsCfg::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<EventsCfg*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // repeated .dmi.EventCfg items = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        do {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          parser_till_end = ::dmi::EventCfg::_InternalParse;
+          object = msg->add_items();
+          if (size > end - ptr) goto len_delim_till_end;
+          ptr += size;
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+              {parser_till_end, object}, ptr - size, ptr));
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 10 && (ptr += 1));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool EventsCfg::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.EventsCfg)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .dmi.EventCfg items = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+                input, add_items()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.EventsCfg)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.EventsCfg)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void EventsCfg::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.EventsCfg)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // repeated .dmi.EventCfg items = 1;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->items_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1,
+      this->items(static_cast<int>(i)),
+      output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.EventsCfg)
+}
+
+::google::protobuf::uint8* EventsCfg::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.EventsCfg)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // repeated .dmi.EventCfg items = 1;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->items_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, this->items(static_cast<int>(i)), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.EventsCfg)
+  return target;
+}
+
+size_t EventsCfg::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.EventsCfg)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated .dmi.EventCfg items = 1;
+  {
+    unsigned int count = static_cast<unsigned int>(this->items_size());
+    total_size += 1UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->items(static_cast<int>(i)));
+    }
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void EventsCfg::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.EventsCfg)
+  GOOGLE_DCHECK_NE(&from, this);
+  const EventsCfg* source =
+      ::google::protobuf::DynamicCastToGenerated<EventsCfg>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.EventsCfg)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.EventsCfg)
+    MergeFrom(*source);
+  }
+}
+
+void EventsCfg::MergeFrom(const EventsCfg& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.EventsCfg)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  items_.MergeFrom(from.items_);
+}
+
+void EventsCfg::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.EventsCfg)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EventsCfg::CopyFrom(const EventsCfg& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.EventsCfg)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool EventsCfg::IsInitialized() const {
+  return true;
+}
+
+void EventsCfg::Swap(EventsCfg* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void EventsCfg::InternalSwap(EventsCfg* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  CastToBase(&items_)->InternalSwap(CastToBase(&other->items_));
+}
+
+::google::protobuf::Metadata EventsCfg::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ListEventsResponse::InitAsDefaultInstance() {
+  ::dmi::_ListEventsResponse_default_instance_._instance.get_mutable()->events_ = const_cast< ::dmi::EventsCfg*>(
+      ::dmi::EventsCfg::internal_default_instance());
+}
+class ListEventsResponse::HasBitSetters {
+ public:
+  static const ::dmi::EventsCfg& events(const ListEventsResponse* msg);
+};
+
+const ::dmi::EventsCfg&
+ListEventsResponse::HasBitSetters::events(const ListEventsResponse* msg) {
+  return *msg->events_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ListEventsResponse::kStatusFieldNumber;
+const int ListEventsResponse::kReasonFieldNumber;
+const int ListEventsResponse::kEventsFieldNumber;
+const int ListEventsResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ListEventsResponse::ListEventsResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ListEventsResponse)
+}
+ListEventsResponse::ListEventsResponse(const ListEventsResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_events()) {
+    events_ = new ::dmi::EventsCfg(*from.events_);
+  } else {
+    events_ = nullptr;
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.ListEventsResponse)
+}
+
+void ListEventsResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ListEventsResponse_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&events_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&events_)) + sizeof(reason_));
+}
+
+ListEventsResponse::~ListEventsResponse() {
+  // @@protoc_insertion_point(destructor:dmi.ListEventsResponse)
+  SharedDtor();
+}
+
+void ListEventsResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete events_;
+}
+
+void ListEventsResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ListEventsResponse& ListEventsResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ListEventsResponse_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ListEventsResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ListEventsResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && events_ != nullptr) {
+    delete events_;
+  }
+  events_ = nullptr;
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ListEventsResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ListEventsResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ListEventsResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::ListEventsResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.EventsCfg events = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::EventsCfg::_InternalParse;
+        object = msg->mutable_events();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ListEventsResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ListEventsResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ListEventsResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ListEventsResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::ListEventsResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.EventsCfg events = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_events()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ListEventsResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ListEventsResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ListEventsResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ListEventsResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ListEventsResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.ListEventsResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // .dmi.EventsCfg events = 3;
+  if (this->has_events()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::events(this), output);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ListEventsResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ListEventsResponse)
+}
+
+::google::protobuf::uint8* ListEventsResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ListEventsResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.ListEventsResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // .dmi.EventsCfg events = 3;
+  if (this->has_events()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::events(this), target);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ListEventsResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ListEventsResponse)
+  return target;
+}
+
+size_t ListEventsResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ListEventsResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.EventsCfg events = 3;
+  if (this->has_events()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *events_);
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.ListEventsResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ListEventsResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ListEventsResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ListEventsResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<ListEventsResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ListEventsResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ListEventsResponse)
+    MergeFrom(*source);
+  }
+}
+
+void ListEventsResponse::MergeFrom(const ListEventsResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ListEventsResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_events()) {
+    mutable_events()->::dmi::EventsCfg::MergeFrom(from.events());
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void ListEventsResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ListEventsResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ListEventsResponse::CopyFrom(const ListEventsResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ListEventsResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ListEventsResponse::IsInitialized() const {
+  return true;
+}
+
+void ListEventsResponse::Swap(ListEventsResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ListEventsResponse::InternalSwap(ListEventsResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(events_, other->events_);
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata ListEventsResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void EventsConfigurationRequest::InitAsDefaultInstance() {
+  ::dmi::_EventsConfigurationRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+  ::dmi::_EventsConfigurationRequest_default_instance_.changes_ = const_cast< ::dmi::EventsCfg*>(
+      ::dmi::EventsCfg::internal_default_instance());
+  ::dmi::_EventsConfigurationRequest_default_instance_.reset_to_default_ = false;
+}
+class EventsConfigurationRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const EventsConfigurationRequest* msg);
+  static const ::dmi::EventsCfg& changes(const EventsConfigurationRequest* msg);
+};
+
+const ::dmi::Uuid&
+EventsConfigurationRequest::HasBitSetters::device_uuid(const EventsConfigurationRequest* msg) {
+  return *msg->device_uuid_;
+}
+const ::dmi::EventsCfg&
+EventsConfigurationRequest::HasBitSetters::changes(const EventsConfigurationRequest* msg) {
+  return *msg->operation_.changes_;
+}
+void EventsConfigurationRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+void EventsConfigurationRequest::set_allocated_changes(::dmi::EventsCfg* changes) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  clear_operation();
+  if (changes) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      changes = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, changes, submessage_arena);
+    }
+    set_has_changes();
+    operation_.changes_ = changes;
+  }
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventsConfigurationRequest.changes)
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int EventsConfigurationRequest::kDeviceUuidFieldNumber;
+const int EventsConfigurationRequest::kChangesFieldNumber;
+const int EventsConfigurationRequest::kResetToDefaultFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+EventsConfigurationRequest::EventsConfigurationRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.EventsConfigurationRequest)
+}
+EventsConfigurationRequest::EventsConfigurationRequest(const EventsConfigurationRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  clear_has_operation();
+  switch (from.operation_case()) {
+    case kChanges: {
+      mutable_changes()->::dmi::EventsCfg::MergeFrom(from.changes());
+      break;
+    }
+    case kResetToDefault: {
+      set_reset_to_default(from.reset_to_default());
+      break;
+    }
+    case OPERATION_NOT_SET: {
+      break;
+    }
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.EventsConfigurationRequest)
+}
+
+void EventsConfigurationRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_EventsConfigurationRequest_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  device_uuid_ = nullptr;
+  clear_has_operation();
+}
+
+EventsConfigurationRequest::~EventsConfigurationRequest() {
+  // @@protoc_insertion_point(destructor:dmi.EventsConfigurationRequest)
+  SharedDtor();
+}
+
+void EventsConfigurationRequest::SharedDtor() {
+  if (this != internal_default_instance()) delete device_uuid_;
+  if (has_operation()) {
+    clear_operation();
+  }
+}
+
+void EventsConfigurationRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const EventsConfigurationRequest& EventsConfigurationRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_EventsConfigurationRequest_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void EventsConfigurationRequest::clear_operation() {
+// @@protoc_insertion_point(one_of_clear_start:dmi.EventsConfigurationRequest)
+  switch (operation_case()) {
+    case kChanges: {
+      delete operation_.changes_;
+      break;
+    }
+    case kResetToDefault: {
+      // No need to clear
+      break;
+    }
+    case OPERATION_NOT_SET: {
+      break;
+    }
+  }
+  _oneof_case_[0] = OPERATION_NOT_SET;
+}
+
+
+void EventsConfigurationRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.EventsConfigurationRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  clear_operation();
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* EventsConfigurationRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<EventsConfigurationRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.EventsCfg changes = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::EventsCfg::_InternalParse;
+        object = msg->mutable_changes();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // bool reset_to_default = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
+        msg->set_reset_to_default(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool EventsConfigurationRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.EventsConfigurationRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.EventsCfg changes = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_changes()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // bool reset_to_default = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
+          clear_operation();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &operation_.reset_to_default_)));
+          set_has_reset_to_default();
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.EventsConfigurationRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.EventsConfigurationRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void EventsConfigurationRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.EventsConfigurationRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // .dmi.EventsCfg changes = 2;
+  if (has_changes()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::changes(this), output);
+  }
+
+  // bool reset_to_default = 3;
+  if (has_reset_to_default()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->reset_to_default(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.EventsConfigurationRequest)
+}
+
+::google::protobuf::uint8* EventsConfigurationRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.EventsConfigurationRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // .dmi.EventsCfg changes = 2;
+  if (has_changes()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::changes(this), target);
+  }
+
+  // bool reset_to_default = 3;
+  if (has_reset_to_default()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->reset_to_default(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.EventsConfigurationRequest)
+  return target;
+}
+
+size_t EventsConfigurationRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.EventsConfigurationRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  switch (operation_case()) {
+    // .dmi.EventsCfg changes = 2;
+    case kChanges: {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          *operation_.changes_);
+      break;
+    }
+    // bool reset_to_default = 3;
+    case kResetToDefault: {
+      total_size += 1 + 1;
+      break;
+    }
+    case OPERATION_NOT_SET: {
+      break;
+    }
+  }
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void EventsConfigurationRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.EventsConfigurationRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const EventsConfigurationRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<EventsConfigurationRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.EventsConfigurationRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.EventsConfigurationRequest)
+    MergeFrom(*source);
+  }
+}
+
+void EventsConfigurationRequest::MergeFrom(const EventsConfigurationRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.EventsConfigurationRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+  switch (from.operation_case()) {
+    case kChanges: {
+      mutable_changes()->::dmi::EventsCfg::MergeFrom(from.changes());
+      break;
+    }
+    case kResetToDefault: {
+      set_reset_to_default(from.reset_to_default());
+      break;
+    }
+    case OPERATION_NOT_SET: {
+      break;
+    }
+  }
+}
+
+void EventsConfigurationRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.EventsConfigurationRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EventsConfigurationRequest::CopyFrom(const EventsConfigurationRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.EventsConfigurationRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool EventsConfigurationRequest::IsInitialized() const {
+  return true;
+}
+
+void EventsConfigurationRequest::Swap(EventsConfigurationRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void EventsConfigurationRequest::InternalSwap(EventsConfigurationRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(device_uuid_, other->device_uuid_);
+  swap(operation_, other->operation_);
+  swap(_oneof_case_[0], other->_oneof_case_[0]);
+}
+
+::google::protobuf::Metadata EventsConfigurationRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void EventsConfigurationResponse::InitAsDefaultInstance() {
+}
+class EventsConfigurationResponse::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int EventsConfigurationResponse::kStatusFieldNumber;
+const int EventsConfigurationResponse::kReasonFieldNumber;
+const int EventsConfigurationResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+EventsConfigurationResponse::EventsConfigurationResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.EventsConfigurationResponse)
+}
+EventsConfigurationResponse::EventsConfigurationResponse(const EventsConfigurationResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.EventsConfigurationResponse)
+}
+
+void EventsConfigurationResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_EventsConfigurationResponse_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+}
+
+EventsConfigurationResponse::~EventsConfigurationResponse() {
+  // @@protoc_insertion_point(destructor:dmi.EventsConfigurationResponse)
+  SharedDtor();
+}
+
+void EventsConfigurationResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void EventsConfigurationResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const EventsConfigurationResponse& EventsConfigurationResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_EventsConfigurationResponse_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void EventsConfigurationResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.EventsConfigurationResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* EventsConfigurationResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<EventsConfigurationResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.EventsConfigurationResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::EventsConfigurationResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.EventsConfigurationResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool EventsConfigurationResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.EventsConfigurationResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.EventsConfigurationResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::EventsConfigurationResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.EventsConfigurationResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.EventsConfigurationResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.EventsConfigurationResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void EventsConfigurationResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.EventsConfigurationResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.EventsConfigurationResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.EventsConfigurationResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.EventsConfigurationResponse)
+}
+
+::google::protobuf::uint8* EventsConfigurationResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.EventsConfigurationResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.EventsConfigurationResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.EventsConfigurationResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.EventsConfigurationResponse)
+  return target;
+}
+
+size_t EventsConfigurationResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.EventsConfigurationResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.EventsConfigurationResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void EventsConfigurationResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.EventsConfigurationResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const EventsConfigurationResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<EventsConfigurationResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.EventsConfigurationResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.EventsConfigurationResponse)
+    MergeFrom(*source);
+  }
+}
+
+void EventsConfigurationResponse::MergeFrom(const EventsConfigurationResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.EventsConfigurationResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void EventsConfigurationResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.EventsConfigurationResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EventsConfigurationResponse::CopyFrom(const EventsConfigurationResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.EventsConfigurationResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool EventsConfigurationResponse::IsInitialized() const {
+  return true;
+}
+
+void EventsConfigurationResponse::Swap(EventsConfigurationResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void EventsConfigurationResponse::InternalSwap(EventsConfigurationResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata EventsConfigurationResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void EventMetaData::InitAsDefaultInstance() {
+  ::dmi::_EventMetaData_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+  ::dmi::_EventMetaData_default_instance_._instance.get_mutable()->component_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class EventMetaData::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const EventMetaData* msg);
+  static const ::dmi::Uuid& component_uuid(const EventMetaData* msg);
+};
+
+const ::dmi::Uuid&
+EventMetaData::HasBitSetters::device_uuid(const EventMetaData* msg) {
+  return *msg->device_uuid_;
+}
+const ::dmi::Uuid&
+EventMetaData::HasBitSetters::component_uuid(const EventMetaData* msg) {
+  return *msg->component_uuid_;
+}
+void EventMetaData::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+void EventMetaData::clear_component_uuid() {
+  if (GetArenaNoVirtual() == nullptr && component_uuid_ != nullptr) {
+    delete component_uuid_;
+  }
+  component_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int EventMetaData::kDeviceUuidFieldNumber;
+const int EventMetaData::kComponentUuidFieldNumber;
+const int EventMetaData::kComponentNameFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+EventMetaData::EventMetaData()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.EventMetaData)
+}
+EventMetaData::EventMetaData(const EventMetaData& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  component_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.component_name().size() > 0) {
+    component_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.component_name_);
+  }
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  if (from.has_component_uuid()) {
+    component_uuid_ = new ::dmi::Uuid(*from.component_uuid_);
+  } else {
+    component_uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.EventMetaData)
+}
+
+void EventMetaData::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_EventMetaData_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  component_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&device_uuid_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&component_uuid_) -
+      reinterpret_cast<char*>(&device_uuid_)) + sizeof(component_uuid_));
+}
+
+EventMetaData::~EventMetaData() {
+  // @@protoc_insertion_point(destructor:dmi.EventMetaData)
+  SharedDtor();
+}
+
+void EventMetaData::SharedDtor() {
+  component_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete device_uuid_;
+  if (this != internal_default_instance()) delete component_uuid_;
+}
+
+void EventMetaData::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const EventMetaData& EventMetaData::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_EventMetaData_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void EventMetaData::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.EventMetaData)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  component_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && component_uuid_ != nullptr) {
+    delete component_uuid_;
+  }
+  component_uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* EventMetaData::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<EventMetaData*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.Uuid component_uuid = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_component_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string component_name = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.EventMetaData.component_name");
+        object = msg->mutable_component_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool EventMetaData::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.EventMetaData)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Uuid component_uuid = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_component_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string component_name = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_component_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->component_name().data(), static_cast<int>(this->component_name().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.EventMetaData.component_name"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.EventMetaData)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.EventMetaData)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void EventMetaData::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.EventMetaData)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::component_uuid(this), output);
+  }
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->component_name().data(), static_cast<int>(this->component_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.EventMetaData.component_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->component_name(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.EventMetaData)
+}
+
+::google::protobuf::uint8* EventMetaData::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.EventMetaData)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::component_uuid(this), target);
+  }
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->component_name().data(), static_cast<int>(this->component_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.EventMetaData.component_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->component_name(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.EventMetaData)
+  return target;
+}
+
+size_t EventMetaData::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.EventMetaData)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->component_name());
+  }
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *component_uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void EventMetaData::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.EventMetaData)
+  GOOGLE_DCHECK_NE(&from, this);
+  const EventMetaData* source =
+      ::google::protobuf::DynamicCastToGenerated<EventMetaData>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.EventMetaData)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.EventMetaData)
+    MergeFrom(*source);
+  }
+}
+
+void EventMetaData::MergeFrom(const EventMetaData& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.EventMetaData)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.component_name().size() > 0) {
+
+    component_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.component_name_);
+  }
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+  if (from.has_component_uuid()) {
+    mutable_component_uuid()->::dmi::Uuid::MergeFrom(from.component_uuid());
+  }
+}
+
+void EventMetaData::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.EventMetaData)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EventMetaData::CopyFrom(const EventMetaData& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.EventMetaData)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool EventMetaData::IsInitialized() const {
+  return true;
+}
+
+void EventMetaData::Swap(EventMetaData* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void EventMetaData::InternalSwap(EventMetaData* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  component_name_.Swap(&other->component_name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(device_uuid_, other->device_uuid_);
+  swap(component_uuid_, other->component_uuid_);
+}
+
+::google::protobuf::Metadata EventMetaData::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void Event::InitAsDefaultInstance() {
+  ::dmi::_Event_default_instance_._instance.get_mutable()->event_metadata_ = const_cast< ::dmi::EventMetaData*>(
+      ::dmi::EventMetaData::internal_default_instance());
+  ::dmi::_Event_default_instance_._instance.get_mutable()->raised_ts_ = const_cast< ::google::protobuf::Timestamp*>(
+      ::google::protobuf::Timestamp::internal_default_instance());
+  ::dmi::_Event_default_instance_._instance.get_mutable()->threshold_info_ = const_cast< ::dmi::ThresholdInformation*>(
+      ::dmi::ThresholdInformation::internal_default_instance());
+}
+class Event::HasBitSetters {
+ public:
+  static const ::dmi::EventMetaData& event_metadata(const Event* msg);
+  static const ::google::protobuf::Timestamp& raised_ts(const Event* msg);
+  static const ::dmi::ThresholdInformation& threshold_info(const Event* msg);
+};
+
+const ::dmi::EventMetaData&
+Event::HasBitSetters::event_metadata(const Event* msg) {
+  return *msg->event_metadata_;
+}
+const ::google::protobuf::Timestamp&
+Event::HasBitSetters::raised_ts(const Event* msg) {
+  return *msg->raised_ts_;
+}
+const ::dmi::ThresholdInformation&
+Event::HasBitSetters::threshold_info(const Event* msg) {
+  return *msg->threshold_info_;
+}
+void Event::clear_raised_ts() {
+  if (GetArenaNoVirtual() == nullptr && raised_ts_ != nullptr) {
+    delete raised_ts_;
+  }
+  raised_ts_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Event::kEventMetadataFieldNumber;
+const int Event::kEventIdFieldNumber;
+const int Event::kRaisedTsFieldNumber;
+const int Event::kThresholdInfoFieldNumber;
+const int Event::kAddInfoFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Event::Event()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.Event)
+}
+Event::Event(const Event& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  add_info_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.add_info().size() > 0) {
+    add_info_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.add_info_);
+  }
+  if (from.has_event_metadata()) {
+    event_metadata_ = new ::dmi::EventMetaData(*from.event_metadata_);
+  } else {
+    event_metadata_ = nullptr;
+  }
+  if (from.has_raised_ts()) {
+    raised_ts_ = new ::google::protobuf::Timestamp(*from.raised_ts_);
+  } else {
+    raised_ts_ = nullptr;
+  }
+  if (from.has_threshold_info()) {
+    threshold_info_ = new ::dmi::ThresholdInformation(*from.threshold_info_);
+  } else {
+    threshold_info_ = nullptr;
+  }
+  event_id_ = from.event_id_;
+  // @@protoc_insertion_point(copy_constructor:dmi.Event)
+}
+
+void Event::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_Event_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  add_info_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&event_metadata_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&event_id_) -
+      reinterpret_cast<char*>(&event_metadata_)) + sizeof(event_id_));
+}
+
+Event::~Event() {
+  // @@protoc_insertion_point(destructor:dmi.Event)
+  SharedDtor();
+}
+
+void Event::SharedDtor() {
+  add_info_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete event_metadata_;
+  if (this != internal_default_instance()) delete raised_ts_;
+  if (this != internal_default_instance()) delete threshold_info_;
+}
+
+void Event::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const Event& Event::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_Event_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void Event::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.Event)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  add_info_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && event_metadata_ != nullptr) {
+    delete event_metadata_;
+  }
+  event_metadata_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && raised_ts_ != nullptr) {
+    delete raised_ts_;
+  }
+  raised_ts_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && threshold_info_ != nullptr) {
+    delete threshold_info_;
+  }
+  threshold_info_ = nullptr;
+  event_id_ = 0;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* Event::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<Event*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.EventMetaData event_metadata = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::EventMetaData::_InternalParse;
+        object = msg->mutable_event_metadata();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.EventIds event_id = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_event_id(static_cast<::dmi::EventIds>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .google.protobuf.Timestamp raised_ts = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::google::protobuf::Timestamp::_InternalParse;
+        object = msg->mutable_raised_ts();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.ThresholdInformation threshold_info = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::ThresholdInformation::_InternalParse;
+        object = msg->mutable_threshold_info();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string add_info = 5;
+      case 5: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.Event.add_info");
+        object = msg->mutable_add_info();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool Event::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.Event)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.EventMetaData event_metadata = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_event_metadata()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.EventIds event_id = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_event_id(static_cast< ::dmi::EventIds >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .google.protobuf.Timestamp raised_ts = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_raised_ts()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ThresholdInformation threshold_info = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_threshold_info()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string add_info = 5;
+      case 5: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (42 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_add_info()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->add_info().data(), static_cast<int>(this->add_info().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.Event.add_info"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.Event)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.Event)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void Event::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.Event)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.EventMetaData event_metadata = 1;
+  if (this->has_event_metadata()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::event_metadata(this), output);
+  }
+
+  // .dmi.EventIds event_id = 2;
+  if (this->event_id() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->event_id(), output);
+  }
+
+  // .google.protobuf.Timestamp raised_ts = 3;
+  if (this->has_raised_ts()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::raised_ts(this), output);
+  }
+
+  // .dmi.ThresholdInformation threshold_info = 4;
+  if (this->has_threshold_info()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      4, HasBitSetters::threshold_info(this), output);
+  }
+
+  // string add_info = 5;
+  if (this->add_info().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->add_info().data(), static_cast<int>(this->add_info().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Event.add_info");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      5, this->add_info(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.Event)
+}
+
+::google::protobuf::uint8* Event::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.Event)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.EventMetaData event_metadata = 1;
+  if (this->has_event_metadata()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::event_metadata(this), target);
+  }
+
+  // .dmi.EventIds event_id = 2;
+  if (this->event_id() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->event_id(), target);
+  }
+
+  // .google.protobuf.Timestamp raised_ts = 3;
+  if (this->has_raised_ts()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::raised_ts(this), target);
+  }
+
+  // .dmi.ThresholdInformation threshold_info = 4;
+  if (this->has_threshold_info()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        4, HasBitSetters::threshold_info(this), target);
+  }
+
+  // string add_info = 5;
+  if (this->add_info().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->add_info().data(), static_cast<int>(this->add_info().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.Event.add_info");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        5, this->add_info(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.Event)
+  return target;
+}
+
+size_t Event::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.Event)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string add_info = 5;
+  if (this->add_info().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->add_info());
+  }
+
+  // .dmi.EventMetaData event_metadata = 1;
+  if (this->has_event_metadata()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *event_metadata_);
+  }
+
+  // .google.protobuf.Timestamp raised_ts = 3;
+  if (this->has_raised_ts()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *raised_ts_);
+  }
+
+  // .dmi.ThresholdInformation threshold_info = 4;
+  if (this->has_threshold_info()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *threshold_info_);
+  }
+
+  // .dmi.EventIds event_id = 2;
+  if (this->event_id() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->event_id());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void Event::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.Event)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Event* source =
+      ::google::protobuf::DynamicCastToGenerated<Event>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.Event)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.Event)
+    MergeFrom(*source);
+  }
+}
+
+void Event::MergeFrom(const Event& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.Event)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.add_info().size() > 0) {
+
+    add_info_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.add_info_);
+  }
+  if (from.has_event_metadata()) {
+    mutable_event_metadata()->::dmi::EventMetaData::MergeFrom(from.event_metadata());
+  }
+  if (from.has_raised_ts()) {
+    mutable_raised_ts()->::google::protobuf::Timestamp::MergeFrom(from.raised_ts());
+  }
+  if (from.has_threshold_info()) {
+    mutable_threshold_info()->::dmi::ThresholdInformation::MergeFrom(from.threshold_info());
+  }
+  if (from.event_id() != 0) {
+    set_event_id(from.event_id());
+  }
+}
+
+void Event::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.Event)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Event::CopyFrom(const Event& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.Event)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Event::IsInitialized() const {
+  return true;
+}
+
+void Event::Swap(Event* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Event::InternalSwap(Event* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  add_info_.Swap(&other->add_info_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(event_metadata_, other->event_metadata_);
+  swap(raised_ts_, other->raised_ts_);
+  swap(threshold_info_, other->threshold_info_);
+  swap(event_id_, other->event_id_);
+}
+
+::google::protobuf::Metadata Event::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> PROTOBUF_NOINLINE ::dmi::ValueType* Arena::CreateMaybeMessage< ::dmi::ValueType >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ValueType >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::WaterMarks* Arena::CreateMaybeMessage< ::dmi::WaterMarks >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::WaterMarks >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::Thresholds* Arena::CreateMaybeMessage< ::dmi::Thresholds >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::Thresholds >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ThresholdInformation* Arena::CreateMaybeMessage< ::dmi::ThresholdInformation >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ThresholdInformation >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::EventCfg* Arena::CreateMaybeMessage< ::dmi::EventCfg >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::EventCfg >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::EventsCfg* Arena::CreateMaybeMessage< ::dmi::EventsCfg >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::EventsCfg >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ListEventsResponse* Arena::CreateMaybeMessage< ::dmi::ListEventsResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ListEventsResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::EventsConfigurationRequest* Arena::CreateMaybeMessage< ::dmi::EventsConfigurationRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::EventsConfigurationRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::EventsConfigurationResponse* Arena::CreateMaybeMessage< ::dmi::EventsConfigurationResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::EventsConfigurationResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::EventMetaData* Arena::CreateMaybeMessage< ::dmi::EventMetaData >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::EventMetaData >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::Event* Arena::CreateMaybeMessage< ::dmi::Event >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::Event >(arena);
+}
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+#include <google/protobuf/port_undef.inc>
diff --git a/cpp/dmi/hw_events_mgmt_service.pb.h b/cpp/dmi/hw_events_mgmt_service.pb.h
new file mode 100644
index 0000000..472a6a9
--- /dev/null
+++ b/cpp/dmi/hw_events_mgmt_service.pb.h
@@ -0,0 +1,3099 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/hw_events_mgmt_service.proto
+
+#ifndef PROTOBUF_INCLUDED_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto
+#define PROTOBUF_INCLUDED_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto
+
+#include <limits>
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+#if PROTOBUF_VERSION < 3007000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3007000 < PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/port_undef.inc>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/inlined_string_field.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+#include "dmi/commons.pb.h"
+#include "dmi/hw.pb.h"
+#include <google/protobuf/timestamp.pb.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+#define PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto
+
+// Internal implementation detail -- do not use these members.
+struct TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto {
+  static const ::google::protobuf::internal::ParseTableField entries[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::AuxillaryParseTableField aux[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::ParseTable schema[11]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
+  static const ::google::protobuf::uint32 offsets[];
+};
+void AddDescriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto();
+namespace dmi {
+class Event;
+class EventDefaultTypeInternal;
+extern EventDefaultTypeInternal _Event_default_instance_;
+class EventCfg;
+class EventCfgDefaultTypeInternal;
+extern EventCfgDefaultTypeInternal _EventCfg_default_instance_;
+class EventMetaData;
+class EventMetaDataDefaultTypeInternal;
+extern EventMetaDataDefaultTypeInternal _EventMetaData_default_instance_;
+class EventsCfg;
+class EventsCfgDefaultTypeInternal;
+extern EventsCfgDefaultTypeInternal _EventsCfg_default_instance_;
+class EventsConfigurationRequest;
+class EventsConfigurationRequestDefaultTypeInternal;
+extern EventsConfigurationRequestDefaultTypeInternal _EventsConfigurationRequest_default_instance_;
+class EventsConfigurationResponse;
+class EventsConfigurationResponseDefaultTypeInternal;
+extern EventsConfigurationResponseDefaultTypeInternal _EventsConfigurationResponse_default_instance_;
+class ListEventsResponse;
+class ListEventsResponseDefaultTypeInternal;
+extern ListEventsResponseDefaultTypeInternal _ListEventsResponse_default_instance_;
+class ThresholdInformation;
+class ThresholdInformationDefaultTypeInternal;
+extern ThresholdInformationDefaultTypeInternal _ThresholdInformation_default_instance_;
+class Thresholds;
+class ThresholdsDefaultTypeInternal;
+extern ThresholdsDefaultTypeInternal _Thresholds_default_instance_;
+class ValueType;
+class ValueTypeDefaultTypeInternal;
+extern ValueTypeDefaultTypeInternal _ValueType_default_instance_;
+class WaterMarks;
+class WaterMarksDefaultTypeInternal;
+extern WaterMarksDefaultTypeInternal _WaterMarks_default_instance_;
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> ::dmi::Event* Arena::CreateMaybeMessage<::dmi::Event>(Arena*);
+template<> ::dmi::EventCfg* Arena::CreateMaybeMessage<::dmi::EventCfg>(Arena*);
+template<> ::dmi::EventMetaData* Arena::CreateMaybeMessage<::dmi::EventMetaData>(Arena*);
+template<> ::dmi::EventsCfg* Arena::CreateMaybeMessage<::dmi::EventsCfg>(Arena*);
+template<> ::dmi::EventsConfigurationRequest* Arena::CreateMaybeMessage<::dmi::EventsConfigurationRequest>(Arena*);
+template<> ::dmi::EventsConfigurationResponse* Arena::CreateMaybeMessage<::dmi::EventsConfigurationResponse>(Arena*);
+template<> ::dmi::ListEventsResponse* Arena::CreateMaybeMessage<::dmi::ListEventsResponse>(Arena*);
+template<> ::dmi::ThresholdInformation* Arena::CreateMaybeMessage<::dmi::ThresholdInformation>(Arena*);
+template<> ::dmi::Thresholds* Arena::CreateMaybeMessage<::dmi::Thresholds>(Arena*);
+template<> ::dmi::ValueType* Arena::CreateMaybeMessage<::dmi::ValueType>(Arena*);
+template<> ::dmi::WaterMarks* Arena::CreateMaybeMessage<::dmi::WaterMarks>(Arena*);
+}  // namespace protobuf
+}  // namespace google
+namespace dmi {
+
+enum ListEventsResponse_Reason {
+  ListEventsResponse_Reason_UNDEFINED_REASON = 0,
+  ListEventsResponse_Reason_UNKNOWN_DEVICE = 1,
+  ListEventsResponse_Reason_INTERNAL_ERROR = 2,
+  ListEventsResponse_Reason_DEVICE_UNREACHABLE = 3,
+  ListEventsResponse_Reason_ListEventsResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ListEventsResponse_Reason_ListEventsResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ListEventsResponse_Reason_IsValid(int value);
+const ListEventsResponse_Reason ListEventsResponse_Reason_Reason_MIN = ListEventsResponse_Reason_UNDEFINED_REASON;
+const ListEventsResponse_Reason ListEventsResponse_Reason_Reason_MAX = ListEventsResponse_Reason_DEVICE_UNREACHABLE;
+const int ListEventsResponse_Reason_Reason_ARRAYSIZE = ListEventsResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ListEventsResponse_Reason_descriptor();
+inline const ::std::string& ListEventsResponse_Reason_Name(ListEventsResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ListEventsResponse_Reason_descriptor(), value);
+}
+inline bool ListEventsResponse_Reason_Parse(
+    const ::std::string& name, ListEventsResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ListEventsResponse_Reason>(
+    ListEventsResponse_Reason_descriptor(), name, value);
+}
+enum EventsConfigurationResponse_Reason {
+  EventsConfigurationResponse_Reason_UNDEFINED_REASON = 0,
+  EventsConfigurationResponse_Reason_UNKNOWN_DEVICE = 1,
+  EventsConfigurationResponse_Reason_INTERNAL_ERROR = 2,
+  EventsConfigurationResponse_Reason_INVALID_CONFIG = 3,
+  EventsConfigurationResponse_Reason_DEVICE_UNREACHABLE = 4,
+  EventsConfigurationResponse_Reason_EventsConfigurationResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  EventsConfigurationResponse_Reason_EventsConfigurationResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool EventsConfigurationResponse_Reason_IsValid(int value);
+const EventsConfigurationResponse_Reason EventsConfigurationResponse_Reason_Reason_MIN = EventsConfigurationResponse_Reason_UNDEFINED_REASON;
+const EventsConfigurationResponse_Reason EventsConfigurationResponse_Reason_Reason_MAX = EventsConfigurationResponse_Reason_DEVICE_UNREACHABLE;
+const int EventsConfigurationResponse_Reason_Reason_ARRAYSIZE = EventsConfigurationResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* EventsConfigurationResponse_Reason_descriptor();
+inline const ::std::string& EventsConfigurationResponse_Reason_Name(EventsConfigurationResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    EventsConfigurationResponse_Reason_descriptor(), value);
+}
+inline bool EventsConfigurationResponse_Reason_Parse(
+    const ::std::string& name, EventsConfigurationResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<EventsConfigurationResponse_Reason>(
+    EventsConfigurationResponse_Reason_descriptor(), name, value);
+}
+enum EventIds {
+  EVENT_NAME_UNDEFINED = 0,
+  EVENT_TRANSCEIVER_PLUG_OUT = 100,
+  EVENT_TRANSCEIVER_PLUG_IN = 101,
+  EVENT_TRANSCEIVER_VOLTAGE_ABOVE_THRESHOLD = 102,
+  EVENT_TRANSCEIVER_VOLTAGE_BELOW_THRESHOLD = 103,
+  EVENT_TRANSCEIVER_TEMPERATURE_ABOVE_THRESHOLD = 104,
+  EVENT_TRANSCEIVER_TEMPERATURE_BELOW_THRESHOLD = 105,
+  EVENT_TRANSCEIVER_CURRENT_ABOVE_THRESHOLD = 106,
+  EVENT_TRANSCEIVER_CURRENT_BELOW_THRESHOLD = 107,
+  EVENT_TRANSCEIVER_RX_POWER_ABOVE_THRESHOLD = 108,
+  EVENT_TRANSCEIVER_RX_POWER_BELOW_THRESHOLD = 109,
+  EVENT_TRANSCEIVER_TX_POWER_ABOVE_THRESHOLD = 110,
+  EVENT_TRANSCEIVER_TX_POWER_BELOW_THRESHOLD = 111,
+  EVENT_TRANSCEIVER_FAILURE = 112,
+  EVENT_TRANSCEIVER_VOLTAGE_ABOVE_THRESHOLD_RECOVERED = 113,
+  EVENT_TRANSCEIVER_VOLTAGE_BELOW_THRESHOLD_RECOVERED = 114,
+  EVENT_TRANSCEIVER_TEMPERATURE_ABOVE_THRESHOLD_RECOVERED = 115,
+  EVENT_TRANSCEIVER_TEMPERATURE_BELOW_THRESHOLD_RECOVERED = 116,
+  EVENT_TRANSCEIVER_CURRENT_ABOVE_THRESHOLD_RECOVERED = 117,
+  EVENT_TRANSCEIVER_CURRENT_BELOW_THRESHOLD_RECOVERED = 118,
+  EVENT_TRANSCEIVER_RX_POWER_ABOVE_THRESHOLD_RECOVERED = 119,
+  EVENT_TRANSCEIVER_RX_POWER_BELOW_THRESHOLD_RECOVERED = 120,
+  EVENT_TRANSCEIVER_TX_POWER_ABOVE_THRESHOLD_RECOVERED = 121,
+  EVENT_TRANSCEIVER_TX_POWER_BELOW_THRESHOLD_RECOVERED = 122,
+  EVENT_TRANSCEIVER_FAILURE_RECOVERED = 123,
+  EVENT_PSU_PLUG_OUT = 200,
+  EVENT_PSU_PLUG_IN = 201,
+  EVENT_PSU_FAILURE = 202,
+  EVENT_PSU_FAILURE_RECOVERED = 203,
+  EVENT_FAN_FAILURE = 300,
+  EVENT_FAN_PLUG_OUT = 301,
+  EVENT_FAN_PLUG_IN = 302,
+  EVENT_FAN_FAILURE_RECOVERED = 303,
+  EVENT_CPU_TEMPERATURE_ABOVE_CRITICAL = 400,
+  EVENT_CPU_TEMPERATURE_ABOVE_FATAL = 401,
+  EVENT_CPU_TEMPERATURE_ABOVE_CRITICAL_RECOVERED = 402,
+  EVENT_CPU_TEMPERATURE_ABOVE_FATAL_RECOVERED = 403,
+  EVENT_HW_DEVICE_RESET = 500,
+  EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL = 501,
+  EVENT_HW_DEVICE_TEMPERATURE_ABOVE_FATAL = 502,
+  EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL_RECOVERED = 503,
+  EVENT_HW_DEVICE_TEMPERATURE_ABOVE_FATAL_RECOVERED = 504,
+  EventIds_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  EventIds_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool EventIds_IsValid(int value);
+const EventIds EventIds_MIN = EVENT_NAME_UNDEFINED;
+const EventIds EventIds_MAX = EVENT_HW_DEVICE_TEMPERATURE_ABOVE_FATAL_RECOVERED;
+const int EventIds_ARRAYSIZE = EventIds_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* EventIds_descriptor();
+inline const ::std::string& EventIds_Name(EventIds value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    EventIds_descriptor(), value);
+}
+inline bool EventIds_Parse(
+    const ::std::string& name, EventIds* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<EventIds>(
+    EventIds_descriptor(), name, value);
+}
+// ===================================================================
+
+class ValueType final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ValueType) */ {
+ public:
+  ValueType();
+  virtual ~ValueType();
+
+  ValueType(const ValueType& from);
+
+  inline ValueType& operator=(const ValueType& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ValueType(ValueType&& from) noexcept
+    : ValueType() {
+    *this = ::std::move(from);
+  }
+
+  inline ValueType& operator=(ValueType&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ValueType& default_instance();
+
+  enum ValCase {
+    kIntVal = 1,
+    kUintVal = 2,
+    kFloatVal = 3,
+    VAL_NOT_SET = 0,
+  };
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ValueType* internal_default_instance() {
+    return reinterpret_cast<const ValueType*>(
+               &_ValueType_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    0;
+
+  void Swap(ValueType* other);
+  friend void swap(ValueType& a, ValueType& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ValueType* New() const final {
+    return CreateMaybeMessage<ValueType>(nullptr);
+  }
+
+  ValueType* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ValueType>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ValueType& from);
+  void MergeFrom(const ValueType& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ValueType* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // int64 int_val = 1;
+  private:
+  bool has_int_val() const;
+  public:
+  void clear_int_val();
+  static const int kIntValFieldNumber = 1;
+  ::google::protobuf::int64 int_val() const;
+  void set_int_val(::google::protobuf::int64 value);
+
+  // uint64 uint_val = 2;
+  private:
+  bool has_uint_val() const;
+  public:
+  void clear_uint_val();
+  static const int kUintValFieldNumber = 2;
+  ::google::protobuf::uint64 uint_val() const;
+  void set_uint_val(::google::protobuf::uint64 value);
+
+  // float float_val = 3;
+  private:
+  bool has_float_val() const;
+  public:
+  void clear_float_val();
+  static const int kFloatValFieldNumber = 3;
+  float float_val() const;
+  void set_float_val(float value);
+
+  void clear_val();
+  ValCase val_case() const;
+  // @@protoc_insertion_point(class_scope:dmi.ValueType)
+ private:
+  class HasBitSetters;
+  void set_has_int_val();
+  void set_has_uint_val();
+  void set_has_float_val();
+
+  inline bool has_val() const;
+  inline void clear_has_val();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  union ValUnion {
+    ValUnion() {}
+    ::google::protobuf::int64 int_val_;
+    ::google::protobuf::uint64 uint_val_;
+    float float_val_;
+  } val_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  ::google::protobuf::uint32 _oneof_case_[1];
+
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class WaterMarks final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.WaterMarks) */ {
+ public:
+  WaterMarks();
+  virtual ~WaterMarks();
+
+  WaterMarks(const WaterMarks& from);
+
+  inline WaterMarks& operator=(const WaterMarks& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  WaterMarks(WaterMarks&& from) noexcept
+    : WaterMarks() {
+    *this = ::std::move(from);
+  }
+
+  inline WaterMarks& operator=(WaterMarks&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const WaterMarks& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const WaterMarks* internal_default_instance() {
+    return reinterpret_cast<const WaterMarks*>(
+               &_WaterMarks_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    1;
+
+  void Swap(WaterMarks* other);
+  friend void swap(WaterMarks& a, WaterMarks& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline WaterMarks* New() const final {
+    return CreateMaybeMessage<WaterMarks>(nullptr);
+  }
+
+  WaterMarks* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<WaterMarks>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const WaterMarks& from);
+  void MergeFrom(const WaterMarks& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(WaterMarks* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.ValueType high = 1;
+  bool has_high() const;
+  void clear_high();
+  static const int kHighFieldNumber = 1;
+  const ::dmi::ValueType& high() const;
+  ::dmi::ValueType* release_high();
+  ::dmi::ValueType* mutable_high();
+  void set_allocated_high(::dmi::ValueType* high);
+
+  // .dmi.ValueType low = 2;
+  bool has_low() const;
+  void clear_low();
+  static const int kLowFieldNumber = 2;
+  const ::dmi::ValueType& low() const;
+  ::dmi::ValueType* release_low();
+  ::dmi::ValueType* mutable_low();
+  void set_allocated_low(::dmi::ValueType* low);
+
+  // @@protoc_insertion_point(class_scope:dmi.WaterMarks)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::ValueType* high_;
+  ::dmi::ValueType* low_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class Thresholds final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.Thresholds) */ {
+ public:
+  Thresholds();
+  virtual ~Thresholds();
+
+  Thresholds(const Thresholds& from);
+
+  inline Thresholds& operator=(const Thresholds& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Thresholds(Thresholds&& from) noexcept
+    : Thresholds() {
+    *this = ::std::move(from);
+  }
+
+  inline Thresholds& operator=(Thresholds&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const Thresholds& default_instance();
+
+  enum ThresholdCase {
+    kUpper = 1,
+    kLower = 2,
+    THRESHOLD_NOT_SET = 0,
+  };
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Thresholds* internal_default_instance() {
+    return reinterpret_cast<const Thresholds*>(
+               &_Thresholds_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    2;
+
+  void Swap(Thresholds* other);
+  friend void swap(Thresholds& a, Thresholds& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Thresholds* New() const final {
+    return CreateMaybeMessage<Thresholds>(nullptr);
+  }
+
+  Thresholds* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<Thresholds>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const Thresholds& from);
+  void MergeFrom(const Thresholds& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Thresholds* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.WaterMarks upper = 1;
+  bool has_upper() const;
+  void clear_upper();
+  static const int kUpperFieldNumber = 1;
+  const ::dmi::WaterMarks& upper() const;
+  ::dmi::WaterMarks* release_upper();
+  ::dmi::WaterMarks* mutable_upper();
+  void set_allocated_upper(::dmi::WaterMarks* upper);
+
+  // .dmi.WaterMarks lower = 2;
+  bool has_lower() const;
+  void clear_lower();
+  static const int kLowerFieldNumber = 2;
+  const ::dmi::WaterMarks& lower() const;
+  ::dmi::WaterMarks* release_lower();
+  ::dmi::WaterMarks* mutable_lower();
+  void set_allocated_lower(::dmi::WaterMarks* lower);
+
+  void clear_threshold();
+  ThresholdCase threshold_case() const;
+  // @@protoc_insertion_point(class_scope:dmi.Thresholds)
+ private:
+  class HasBitSetters;
+  void set_has_upper();
+  void set_has_lower();
+
+  inline bool has_threshold() const;
+  inline void clear_has_threshold();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  union ThresholdUnion {
+    ThresholdUnion() {}
+    ::dmi::WaterMarks* upper_;
+    ::dmi::WaterMarks* lower_;
+  } threshold_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  ::google::protobuf::uint32 _oneof_case_[1];
+
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ThresholdInformation final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ThresholdInformation) */ {
+ public:
+  ThresholdInformation();
+  virtual ~ThresholdInformation();
+
+  ThresholdInformation(const ThresholdInformation& from);
+
+  inline ThresholdInformation& operator=(const ThresholdInformation& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ThresholdInformation(ThresholdInformation&& from) noexcept
+    : ThresholdInformation() {
+    *this = ::std::move(from);
+  }
+
+  inline ThresholdInformation& operator=(ThresholdInformation&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ThresholdInformation& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ThresholdInformation* internal_default_instance() {
+    return reinterpret_cast<const ThresholdInformation*>(
+               &_ThresholdInformation_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    3;
+
+  void Swap(ThresholdInformation* other);
+  friend void swap(ThresholdInformation& a, ThresholdInformation& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ThresholdInformation* New() const final {
+    return CreateMaybeMessage<ThresholdInformation>(nullptr);
+  }
+
+  ThresholdInformation* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ThresholdInformation>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ThresholdInformation& from);
+  void MergeFrom(const ThresholdInformation& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ThresholdInformation* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.ValueType observed_value = 1;
+  bool has_observed_value() const;
+  void clear_observed_value();
+  static const int kObservedValueFieldNumber = 1;
+  const ::dmi::ValueType& observed_value() const;
+  ::dmi::ValueType* release_observed_value();
+  ::dmi::ValueType* mutable_observed_value();
+  void set_allocated_observed_value(::dmi::ValueType* observed_value);
+
+  // .dmi.Thresholds thresholds = 2;
+  bool has_thresholds() const;
+  void clear_thresholds();
+  static const int kThresholdsFieldNumber = 2;
+  const ::dmi::Thresholds& thresholds() const;
+  ::dmi::Thresholds* release_thresholds();
+  ::dmi::Thresholds* mutable_thresholds();
+  void set_allocated_thresholds(::dmi::Thresholds* thresholds);
+
+  // @@protoc_insertion_point(class_scope:dmi.ThresholdInformation)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::ValueType* observed_value_;
+  ::dmi::Thresholds* thresholds_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class EventCfg final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventCfg) */ {
+ public:
+  EventCfg();
+  virtual ~EventCfg();
+
+  EventCfg(const EventCfg& from);
+
+  inline EventCfg& operator=(const EventCfg& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  EventCfg(EventCfg&& from) noexcept
+    : EventCfg() {
+    *this = ::std::move(from);
+  }
+
+  inline EventCfg& operator=(EventCfg&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const EventCfg& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const EventCfg* internal_default_instance() {
+    return reinterpret_cast<const EventCfg*>(
+               &_EventCfg_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    4;
+
+  void Swap(EventCfg* other);
+  friend void swap(EventCfg& a, EventCfg& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline EventCfg* New() const final {
+    return CreateMaybeMessage<EventCfg>(nullptr);
+  }
+
+  EventCfg* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<EventCfg>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const EventCfg& from);
+  void MergeFrom(const EventCfg& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(EventCfg* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.Thresholds thresholds = 3;
+  bool has_thresholds() const;
+  void clear_thresholds();
+  static const int kThresholdsFieldNumber = 3;
+  const ::dmi::Thresholds& thresholds() const;
+  ::dmi::Thresholds* release_thresholds();
+  ::dmi::Thresholds* mutable_thresholds();
+  void set_allocated_thresholds(::dmi::Thresholds* thresholds);
+
+  // .dmi.EventIds event_id = 1;
+  void clear_event_id();
+  static const int kEventIdFieldNumber = 1;
+  ::dmi::EventIds event_id() const;
+  void set_event_id(::dmi::EventIds value);
+
+  // bool is_configured = 2;
+  void clear_is_configured();
+  static const int kIsConfiguredFieldNumber = 2;
+  bool is_configured() const;
+  void set_is_configured(bool value);
+
+  // @@protoc_insertion_point(class_scope:dmi.EventCfg)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::Thresholds* thresholds_;
+  int event_id_;
+  bool is_configured_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class EventsCfg final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventsCfg) */ {
+ public:
+  EventsCfg();
+  virtual ~EventsCfg();
+
+  EventsCfg(const EventsCfg& from);
+
+  inline EventsCfg& operator=(const EventsCfg& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  EventsCfg(EventsCfg&& from) noexcept
+    : EventsCfg() {
+    *this = ::std::move(from);
+  }
+
+  inline EventsCfg& operator=(EventsCfg&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const EventsCfg& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const EventsCfg* internal_default_instance() {
+    return reinterpret_cast<const EventsCfg*>(
+               &_EventsCfg_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    5;
+
+  void Swap(EventsCfg* other);
+  friend void swap(EventsCfg& a, EventsCfg& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline EventsCfg* New() const final {
+    return CreateMaybeMessage<EventsCfg>(nullptr);
+  }
+
+  EventsCfg* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<EventsCfg>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const EventsCfg& from);
+  void MergeFrom(const EventsCfg& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(EventsCfg* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated .dmi.EventCfg items = 1;
+  int items_size() const;
+  void clear_items();
+  static const int kItemsFieldNumber = 1;
+  ::dmi::EventCfg* mutable_items(int index);
+  ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg >*
+      mutable_items();
+  const ::dmi::EventCfg& items(int index) const;
+  ::dmi::EventCfg* add_items();
+  const ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg >&
+      items() const;
+
+  // @@protoc_insertion_point(class_scope:dmi.EventsCfg)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg > items_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ListEventsResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ListEventsResponse) */ {
+ public:
+  ListEventsResponse();
+  virtual ~ListEventsResponse();
+
+  ListEventsResponse(const ListEventsResponse& from);
+
+  inline ListEventsResponse& operator=(const ListEventsResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ListEventsResponse(ListEventsResponse&& from) noexcept
+    : ListEventsResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline ListEventsResponse& operator=(ListEventsResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ListEventsResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ListEventsResponse* internal_default_instance() {
+    return reinterpret_cast<const ListEventsResponse*>(
+               &_ListEventsResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    6;
+
+  void Swap(ListEventsResponse* other);
+  friend void swap(ListEventsResponse& a, ListEventsResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ListEventsResponse* New() const final {
+    return CreateMaybeMessage<ListEventsResponse>(nullptr);
+  }
+
+  ListEventsResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ListEventsResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ListEventsResponse& from);
+  void MergeFrom(const ListEventsResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ListEventsResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef ListEventsResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    ListEventsResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    ListEventsResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    ListEventsResponse_Reason_INTERNAL_ERROR;
+  static const Reason DEVICE_UNREACHABLE =
+    ListEventsResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return ListEventsResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    ListEventsResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    ListEventsResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    ListEventsResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return ListEventsResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return ListEventsResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return ListEventsResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 4;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 4;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.EventsCfg events = 3;
+  bool has_events() const;
+  void clear_events();
+  static const int kEventsFieldNumber = 3;
+  const ::dmi::EventsCfg& events() const;
+  ::dmi::EventsCfg* release_events();
+  ::dmi::EventsCfg* mutable_events();
+  void set_allocated_events(::dmi::EventsCfg* events);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.ListEventsResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::ListEventsResponse_Reason reason() const;
+  void set_reason(::dmi::ListEventsResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.ListEventsResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  ::dmi::EventsCfg* events_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class EventsConfigurationRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventsConfigurationRequest) */ {
+ public:
+  EventsConfigurationRequest();
+  virtual ~EventsConfigurationRequest();
+
+  EventsConfigurationRequest(const EventsConfigurationRequest& from);
+
+  inline EventsConfigurationRequest& operator=(const EventsConfigurationRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  EventsConfigurationRequest(EventsConfigurationRequest&& from) noexcept
+    : EventsConfigurationRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline EventsConfigurationRequest& operator=(EventsConfigurationRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const EventsConfigurationRequest& default_instance();
+
+  enum OperationCase {
+    kChanges = 2,
+    kResetToDefault = 3,
+    OPERATION_NOT_SET = 0,
+  };
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const EventsConfigurationRequest* internal_default_instance() {
+    return reinterpret_cast<const EventsConfigurationRequest*>(
+               &_EventsConfigurationRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    7;
+
+  void Swap(EventsConfigurationRequest* other);
+  friend void swap(EventsConfigurationRequest& a, EventsConfigurationRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline EventsConfigurationRequest* New() const final {
+    return CreateMaybeMessage<EventsConfigurationRequest>(nullptr);
+  }
+
+  EventsConfigurationRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<EventsConfigurationRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const EventsConfigurationRequest& from);
+  void MergeFrom(const EventsConfigurationRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(EventsConfigurationRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // .dmi.EventsCfg changes = 2;
+  bool has_changes() const;
+  void clear_changes();
+  static const int kChangesFieldNumber = 2;
+  const ::dmi::EventsCfg& changes() const;
+  ::dmi::EventsCfg* release_changes();
+  ::dmi::EventsCfg* mutable_changes();
+  void set_allocated_changes(::dmi::EventsCfg* changes);
+
+  // bool reset_to_default = 3;
+  private:
+  bool has_reset_to_default() const;
+  public:
+  void clear_reset_to_default();
+  static const int kResetToDefaultFieldNumber = 3;
+  bool reset_to_default() const;
+  void set_reset_to_default(bool value);
+
+  void clear_operation();
+  OperationCase operation_case() const;
+  // @@protoc_insertion_point(class_scope:dmi.EventsConfigurationRequest)
+ private:
+  class HasBitSetters;
+  void set_has_changes();
+  void set_has_reset_to_default();
+
+  inline bool has_operation() const;
+  inline void clear_has_operation();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::Uuid* device_uuid_;
+  union OperationUnion {
+    OperationUnion() {}
+    ::dmi::EventsCfg* changes_;
+    bool reset_to_default_;
+  } operation_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  ::google::protobuf::uint32 _oneof_case_[1];
+
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class EventsConfigurationResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventsConfigurationResponse) */ {
+ public:
+  EventsConfigurationResponse();
+  virtual ~EventsConfigurationResponse();
+
+  EventsConfigurationResponse(const EventsConfigurationResponse& from);
+
+  inline EventsConfigurationResponse& operator=(const EventsConfigurationResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  EventsConfigurationResponse(EventsConfigurationResponse&& from) noexcept
+    : EventsConfigurationResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline EventsConfigurationResponse& operator=(EventsConfigurationResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const EventsConfigurationResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const EventsConfigurationResponse* internal_default_instance() {
+    return reinterpret_cast<const EventsConfigurationResponse*>(
+               &_EventsConfigurationResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    8;
+
+  void Swap(EventsConfigurationResponse* other);
+  friend void swap(EventsConfigurationResponse& a, EventsConfigurationResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline EventsConfigurationResponse* New() const final {
+    return CreateMaybeMessage<EventsConfigurationResponse>(nullptr);
+  }
+
+  EventsConfigurationResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<EventsConfigurationResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const EventsConfigurationResponse& from);
+  void MergeFrom(const EventsConfigurationResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(EventsConfigurationResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef EventsConfigurationResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    EventsConfigurationResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    EventsConfigurationResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    EventsConfigurationResponse_Reason_INTERNAL_ERROR;
+  static const Reason INVALID_CONFIG =
+    EventsConfigurationResponse_Reason_INVALID_CONFIG;
+  static const Reason DEVICE_UNREACHABLE =
+    EventsConfigurationResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return EventsConfigurationResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    EventsConfigurationResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    EventsConfigurationResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    EventsConfigurationResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return EventsConfigurationResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return EventsConfigurationResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return EventsConfigurationResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 3;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 3;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.EventsConfigurationResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::EventsConfigurationResponse_Reason reason() const;
+  void set_reason(::dmi::EventsConfigurationResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.EventsConfigurationResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class EventMetaData final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventMetaData) */ {
+ public:
+  EventMetaData();
+  virtual ~EventMetaData();
+
+  EventMetaData(const EventMetaData& from);
+
+  inline EventMetaData& operator=(const EventMetaData& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  EventMetaData(EventMetaData&& from) noexcept
+    : EventMetaData() {
+    *this = ::std::move(from);
+  }
+
+  inline EventMetaData& operator=(EventMetaData&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const EventMetaData& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const EventMetaData* internal_default_instance() {
+    return reinterpret_cast<const EventMetaData*>(
+               &_EventMetaData_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    9;
+
+  void Swap(EventMetaData* other);
+  friend void swap(EventMetaData& a, EventMetaData& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline EventMetaData* New() const final {
+    return CreateMaybeMessage<EventMetaData>(nullptr);
+  }
+
+  EventMetaData* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<EventMetaData>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const EventMetaData& from);
+  void MergeFrom(const EventMetaData& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(EventMetaData* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string component_name = 3;
+  void clear_component_name();
+  static const int kComponentNameFieldNumber = 3;
+  const ::std::string& component_name() const;
+  void set_component_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_component_name(::std::string&& value);
+  #endif
+  void set_component_name(const char* value);
+  void set_component_name(const char* value, size_t size);
+  ::std::string* mutable_component_name();
+  ::std::string* release_component_name();
+  void set_allocated_component_name(::std::string* component_name);
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // .dmi.Uuid component_uuid = 2;
+  bool has_component_uuid() const;
+  void clear_component_uuid();
+  static const int kComponentUuidFieldNumber = 2;
+  const ::dmi::Uuid& component_uuid() const;
+  ::dmi::Uuid* release_component_uuid();
+  ::dmi::Uuid* mutable_component_uuid();
+  void set_allocated_component_uuid(::dmi::Uuid* component_uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.EventMetaData)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr component_name_;
+  ::dmi::Uuid* device_uuid_;
+  ::dmi::Uuid* component_uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class Event final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.Event) */ {
+ public:
+  Event();
+  virtual ~Event();
+
+  Event(const Event& from);
+
+  inline Event& operator=(const Event& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Event(Event&& from) noexcept
+    : Event() {
+    *this = ::std::move(from);
+  }
+
+  inline Event& operator=(Event&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const Event& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Event* internal_default_instance() {
+    return reinterpret_cast<const Event*>(
+               &_Event_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    10;
+
+  void Swap(Event* other);
+  friend void swap(Event& a, Event& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Event* New() const final {
+    return CreateMaybeMessage<Event>(nullptr);
+  }
+
+  Event* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<Event>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const Event& from);
+  void MergeFrom(const Event& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Event* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string add_info = 5;
+  void clear_add_info();
+  static const int kAddInfoFieldNumber = 5;
+  const ::std::string& add_info() const;
+  void set_add_info(const ::std::string& value);
+  #if LANG_CXX11
+  void set_add_info(::std::string&& value);
+  #endif
+  void set_add_info(const char* value);
+  void set_add_info(const char* value, size_t size);
+  ::std::string* mutable_add_info();
+  ::std::string* release_add_info();
+  void set_allocated_add_info(::std::string* add_info);
+
+  // .dmi.EventMetaData event_metadata = 1;
+  bool has_event_metadata() const;
+  void clear_event_metadata();
+  static const int kEventMetadataFieldNumber = 1;
+  const ::dmi::EventMetaData& event_metadata() const;
+  ::dmi::EventMetaData* release_event_metadata();
+  ::dmi::EventMetaData* mutable_event_metadata();
+  void set_allocated_event_metadata(::dmi::EventMetaData* event_metadata);
+
+  // .google.protobuf.Timestamp raised_ts = 3;
+  bool has_raised_ts() const;
+  void clear_raised_ts();
+  static const int kRaisedTsFieldNumber = 3;
+  const ::google::protobuf::Timestamp& raised_ts() const;
+  ::google::protobuf::Timestamp* release_raised_ts();
+  ::google::protobuf::Timestamp* mutable_raised_ts();
+  void set_allocated_raised_ts(::google::protobuf::Timestamp* raised_ts);
+
+  // .dmi.ThresholdInformation threshold_info = 4;
+  bool has_threshold_info() const;
+  void clear_threshold_info();
+  static const int kThresholdInfoFieldNumber = 4;
+  const ::dmi::ThresholdInformation& threshold_info() const;
+  ::dmi::ThresholdInformation* release_threshold_info();
+  ::dmi::ThresholdInformation* mutable_threshold_info();
+  void set_allocated_threshold_info(::dmi::ThresholdInformation* threshold_info);
+
+  // .dmi.EventIds event_id = 2;
+  void clear_event_id();
+  static const int kEventIdFieldNumber = 2;
+  ::dmi::EventIds event_id() const;
+  void set_event_id(::dmi::EventIds value);
+
+  // @@protoc_insertion_point(class_scope:dmi.Event)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr add_info_;
+  ::dmi::EventMetaData* event_metadata_;
+  ::google::protobuf::Timestamp* raised_ts_;
+  ::dmi::ThresholdInformation* threshold_info_;
+  int event_id_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// ValueType
+
+// int64 int_val = 1;
+inline bool ValueType::has_int_val() const {
+  return val_case() == kIntVal;
+}
+inline void ValueType::set_has_int_val() {
+  _oneof_case_[0] = kIntVal;
+}
+inline void ValueType::clear_int_val() {
+  if (has_int_val()) {
+    val_.int_val_ = PROTOBUF_LONGLONG(0);
+    clear_has_val();
+  }
+}
+inline ::google::protobuf::int64 ValueType::int_val() const {
+  // @@protoc_insertion_point(field_get:dmi.ValueType.int_val)
+  if (has_int_val()) {
+    return val_.int_val_;
+  }
+  return PROTOBUF_LONGLONG(0);
+}
+inline void ValueType::set_int_val(::google::protobuf::int64 value) {
+  if (!has_int_val()) {
+    clear_val();
+    set_has_int_val();
+  }
+  val_.int_val_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ValueType.int_val)
+}
+
+// uint64 uint_val = 2;
+inline bool ValueType::has_uint_val() const {
+  return val_case() == kUintVal;
+}
+inline void ValueType::set_has_uint_val() {
+  _oneof_case_[0] = kUintVal;
+}
+inline void ValueType::clear_uint_val() {
+  if (has_uint_val()) {
+    val_.uint_val_ = PROTOBUF_ULONGLONG(0);
+    clear_has_val();
+  }
+}
+inline ::google::protobuf::uint64 ValueType::uint_val() const {
+  // @@protoc_insertion_point(field_get:dmi.ValueType.uint_val)
+  if (has_uint_val()) {
+    return val_.uint_val_;
+  }
+  return PROTOBUF_ULONGLONG(0);
+}
+inline void ValueType::set_uint_val(::google::protobuf::uint64 value) {
+  if (!has_uint_val()) {
+    clear_val();
+    set_has_uint_val();
+  }
+  val_.uint_val_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ValueType.uint_val)
+}
+
+// float float_val = 3;
+inline bool ValueType::has_float_val() const {
+  return val_case() == kFloatVal;
+}
+inline void ValueType::set_has_float_val() {
+  _oneof_case_[0] = kFloatVal;
+}
+inline void ValueType::clear_float_val() {
+  if (has_float_val()) {
+    val_.float_val_ = 0;
+    clear_has_val();
+  }
+}
+inline float ValueType::float_val() const {
+  // @@protoc_insertion_point(field_get:dmi.ValueType.float_val)
+  if (has_float_val()) {
+    return val_.float_val_;
+  }
+  return 0;
+}
+inline void ValueType::set_float_val(float value) {
+  if (!has_float_val()) {
+    clear_val();
+    set_has_float_val();
+  }
+  val_.float_val_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ValueType.float_val)
+}
+
+inline bool ValueType::has_val() const {
+  return val_case() != VAL_NOT_SET;
+}
+inline void ValueType::clear_has_val() {
+  _oneof_case_[0] = VAL_NOT_SET;
+}
+inline ValueType::ValCase ValueType::val_case() const {
+  return ValueType::ValCase(_oneof_case_[0]);
+}
+// -------------------------------------------------------------------
+
+// WaterMarks
+
+// .dmi.ValueType high = 1;
+inline bool WaterMarks::has_high() const {
+  return this != internal_default_instance() && high_ != nullptr;
+}
+inline void WaterMarks::clear_high() {
+  if (GetArenaNoVirtual() == nullptr && high_ != nullptr) {
+    delete high_;
+  }
+  high_ = nullptr;
+}
+inline const ::dmi::ValueType& WaterMarks::high() const {
+  const ::dmi::ValueType* p = high_;
+  // @@protoc_insertion_point(field_get:dmi.WaterMarks.high)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ValueType*>(
+      &::dmi::_ValueType_default_instance_);
+}
+inline ::dmi::ValueType* WaterMarks::release_high() {
+  // @@protoc_insertion_point(field_release:dmi.WaterMarks.high)
+  
+  ::dmi::ValueType* temp = high_;
+  high_ = nullptr;
+  return temp;
+}
+inline ::dmi::ValueType* WaterMarks::mutable_high() {
+  
+  if (high_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ValueType>(GetArenaNoVirtual());
+    high_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.WaterMarks.high)
+  return high_;
+}
+inline void WaterMarks::set_allocated_high(::dmi::ValueType* high) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete high_;
+  }
+  if (high) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      high = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, high, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  high_ = high;
+  // @@protoc_insertion_point(field_set_allocated:dmi.WaterMarks.high)
+}
+
+// .dmi.ValueType low = 2;
+inline bool WaterMarks::has_low() const {
+  return this != internal_default_instance() && low_ != nullptr;
+}
+inline void WaterMarks::clear_low() {
+  if (GetArenaNoVirtual() == nullptr && low_ != nullptr) {
+    delete low_;
+  }
+  low_ = nullptr;
+}
+inline const ::dmi::ValueType& WaterMarks::low() const {
+  const ::dmi::ValueType* p = low_;
+  // @@protoc_insertion_point(field_get:dmi.WaterMarks.low)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ValueType*>(
+      &::dmi::_ValueType_default_instance_);
+}
+inline ::dmi::ValueType* WaterMarks::release_low() {
+  // @@protoc_insertion_point(field_release:dmi.WaterMarks.low)
+  
+  ::dmi::ValueType* temp = low_;
+  low_ = nullptr;
+  return temp;
+}
+inline ::dmi::ValueType* WaterMarks::mutable_low() {
+  
+  if (low_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ValueType>(GetArenaNoVirtual());
+    low_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.WaterMarks.low)
+  return low_;
+}
+inline void WaterMarks::set_allocated_low(::dmi::ValueType* low) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete low_;
+  }
+  if (low) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      low = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, low, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  low_ = low;
+  // @@protoc_insertion_point(field_set_allocated:dmi.WaterMarks.low)
+}
+
+// -------------------------------------------------------------------
+
+// Thresholds
+
+// .dmi.WaterMarks upper = 1;
+inline bool Thresholds::has_upper() const {
+  return threshold_case() == kUpper;
+}
+inline void Thresholds::set_has_upper() {
+  _oneof_case_[0] = kUpper;
+}
+inline void Thresholds::clear_upper() {
+  if (has_upper()) {
+    delete threshold_.upper_;
+    clear_has_threshold();
+  }
+}
+inline ::dmi::WaterMarks* Thresholds::release_upper() {
+  // @@protoc_insertion_point(field_release:dmi.Thresholds.upper)
+  if (has_upper()) {
+    clear_has_threshold();
+      ::dmi::WaterMarks* temp = threshold_.upper_;
+    threshold_.upper_ = nullptr;
+    return temp;
+  } else {
+    return nullptr;
+  }
+}
+inline const ::dmi::WaterMarks& Thresholds::upper() const {
+  // @@protoc_insertion_point(field_get:dmi.Thresholds.upper)
+  return has_upper()
+      ? *threshold_.upper_
+      : *reinterpret_cast< ::dmi::WaterMarks*>(&::dmi::_WaterMarks_default_instance_);
+}
+inline ::dmi::WaterMarks* Thresholds::mutable_upper() {
+  if (!has_upper()) {
+    clear_threshold();
+    set_has_upper();
+    threshold_.upper_ = CreateMaybeMessage< ::dmi::WaterMarks >(
+        GetArenaNoVirtual());
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Thresholds.upper)
+  return threshold_.upper_;
+}
+
+// .dmi.WaterMarks lower = 2;
+inline bool Thresholds::has_lower() const {
+  return threshold_case() == kLower;
+}
+inline void Thresholds::set_has_lower() {
+  _oneof_case_[0] = kLower;
+}
+inline void Thresholds::clear_lower() {
+  if (has_lower()) {
+    delete threshold_.lower_;
+    clear_has_threshold();
+  }
+}
+inline ::dmi::WaterMarks* Thresholds::release_lower() {
+  // @@protoc_insertion_point(field_release:dmi.Thresholds.lower)
+  if (has_lower()) {
+    clear_has_threshold();
+      ::dmi::WaterMarks* temp = threshold_.lower_;
+    threshold_.lower_ = nullptr;
+    return temp;
+  } else {
+    return nullptr;
+  }
+}
+inline const ::dmi::WaterMarks& Thresholds::lower() const {
+  // @@protoc_insertion_point(field_get:dmi.Thresholds.lower)
+  return has_lower()
+      ? *threshold_.lower_
+      : *reinterpret_cast< ::dmi::WaterMarks*>(&::dmi::_WaterMarks_default_instance_);
+}
+inline ::dmi::WaterMarks* Thresholds::mutable_lower() {
+  if (!has_lower()) {
+    clear_threshold();
+    set_has_lower();
+    threshold_.lower_ = CreateMaybeMessage< ::dmi::WaterMarks >(
+        GetArenaNoVirtual());
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Thresholds.lower)
+  return threshold_.lower_;
+}
+
+inline bool Thresholds::has_threshold() const {
+  return threshold_case() != THRESHOLD_NOT_SET;
+}
+inline void Thresholds::clear_has_threshold() {
+  _oneof_case_[0] = THRESHOLD_NOT_SET;
+}
+inline Thresholds::ThresholdCase Thresholds::threshold_case() const {
+  return Thresholds::ThresholdCase(_oneof_case_[0]);
+}
+// -------------------------------------------------------------------
+
+// ThresholdInformation
+
+// .dmi.ValueType observed_value = 1;
+inline bool ThresholdInformation::has_observed_value() const {
+  return this != internal_default_instance() && observed_value_ != nullptr;
+}
+inline void ThresholdInformation::clear_observed_value() {
+  if (GetArenaNoVirtual() == nullptr && observed_value_ != nullptr) {
+    delete observed_value_;
+  }
+  observed_value_ = nullptr;
+}
+inline const ::dmi::ValueType& ThresholdInformation::observed_value() const {
+  const ::dmi::ValueType* p = observed_value_;
+  // @@protoc_insertion_point(field_get:dmi.ThresholdInformation.observed_value)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ValueType*>(
+      &::dmi::_ValueType_default_instance_);
+}
+inline ::dmi::ValueType* ThresholdInformation::release_observed_value() {
+  // @@protoc_insertion_point(field_release:dmi.ThresholdInformation.observed_value)
+  
+  ::dmi::ValueType* temp = observed_value_;
+  observed_value_ = nullptr;
+  return temp;
+}
+inline ::dmi::ValueType* ThresholdInformation::mutable_observed_value() {
+  
+  if (observed_value_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ValueType>(GetArenaNoVirtual());
+    observed_value_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ThresholdInformation.observed_value)
+  return observed_value_;
+}
+inline void ThresholdInformation::set_allocated_observed_value(::dmi::ValueType* observed_value) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete observed_value_;
+  }
+  if (observed_value) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      observed_value = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, observed_value, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  observed_value_ = observed_value;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ThresholdInformation.observed_value)
+}
+
+// .dmi.Thresholds thresholds = 2;
+inline bool ThresholdInformation::has_thresholds() const {
+  return this != internal_default_instance() && thresholds_ != nullptr;
+}
+inline void ThresholdInformation::clear_thresholds() {
+  if (GetArenaNoVirtual() == nullptr && thresholds_ != nullptr) {
+    delete thresholds_;
+  }
+  thresholds_ = nullptr;
+}
+inline const ::dmi::Thresholds& ThresholdInformation::thresholds() const {
+  const ::dmi::Thresholds* p = thresholds_;
+  // @@protoc_insertion_point(field_get:dmi.ThresholdInformation.thresholds)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Thresholds*>(
+      &::dmi::_Thresholds_default_instance_);
+}
+inline ::dmi::Thresholds* ThresholdInformation::release_thresholds() {
+  // @@protoc_insertion_point(field_release:dmi.ThresholdInformation.thresholds)
+  
+  ::dmi::Thresholds* temp = thresholds_;
+  thresholds_ = nullptr;
+  return temp;
+}
+inline ::dmi::Thresholds* ThresholdInformation::mutable_thresholds() {
+  
+  if (thresholds_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Thresholds>(GetArenaNoVirtual());
+    thresholds_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ThresholdInformation.thresholds)
+  return thresholds_;
+}
+inline void ThresholdInformation::set_allocated_thresholds(::dmi::Thresholds* thresholds) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete thresholds_;
+  }
+  if (thresholds) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      thresholds = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, thresholds, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  thresholds_ = thresholds;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ThresholdInformation.thresholds)
+}
+
+// -------------------------------------------------------------------
+
+// EventCfg
+
+// .dmi.EventIds event_id = 1;
+inline void EventCfg::clear_event_id() {
+  event_id_ = 0;
+}
+inline ::dmi::EventIds EventCfg::event_id() const {
+  // @@protoc_insertion_point(field_get:dmi.EventCfg.event_id)
+  return static_cast< ::dmi::EventIds >(event_id_);
+}
+inline void EventCfg::set_event_id(::dmi::EventIds value) {
+  
+  event_id_ = value;
+  // @@protoc_insertion_point(field_set:dmi.EventCfg.event_id)
+}
+
+// bool is_configured = 2;
+inline void EventCfg::clear_is_configured() {
+  is_configured_ = false;
+}
+inline bool EventCfg::is_configured() const {
+  // @@protoc_insertion_point(field_get:dmi.EventCfg.is_configured)
+  return is_configured_;
+}
+inline void EventCfg::set_is_configured(bool value) {
+  
+  is_configured_ = value;
+  // @@protoc_insertion_point(field_set:dmi.EventCfg.is_configured)
+}
+
+// .dmi.Thresholds thresholds = 3;
+inline bool EventCfg::has_thresholds() const {
+  return this != internal_default_instance() && thresholds_ != nullptr;
+}
+inline void EventCfg::clear_thresholds() {
+  if (GetArenaNoVirtual() == nullptr && thresholds_ != nullptr) {
+    delete thresholds_;
+  }
+  thresholds_ = nullptr;
+}
+inline const ::dmi::Thresholds& EventCfg::thresholds() const {
+  const ::dmi::Thresholds* p = thresholds_;
+  // @@protoc_insertion_point(field_get:dmi.EventCfg.thresholds)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Thresholds*>(
+      &::dmi::_Thresholds_default_instance_);
+}
+inline ::dmi::Thresholds* EventCfg::release_thresholds() {
+  // @@protoc_insertion_point(field_release:dmi.EventCfg.thresholds)
+  
+  ::dmi::Thresholds* temp = thresholds_;
+  thresholds_ = nullptr;
+  return temp;
+}
+inline ::dmi::Thresholds* EventCfg::mutable_thresholds() {
+  
+  if (thresholds_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Thresholds>(GetArenaNoVirtual());
+    thresholds_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.EventCfg.thresholds)
+  return thresholds_;
+}
+inline void EventCfg::set_allocated_thresholds(::dmi::Thresholds* thresholds) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete thresholds_;
+  }
+  if (thresholds) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      thresholds = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, thresholds, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  thresholds_ = thresholds;
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventCfg.thresholds)
+}
+
+// -------------------------------------------------------------------
+
+// EventsCfg
+
+// repeated .dmi.EventCfg items = 1;
+inline int EventsCfg::items_size() const {
+  return items_.size();
+}
+inline void EventsCfg::clear_items() {
+  items_.Clear();
+}
+inline ::dmi::EventCfg* EventsCfg::mutable_items(int index) {
+  // @@protoc_insertion_point(field_mutable:dmi.EventsCfg.items)
+  return items_.Mutable(index);
+}
+inline ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg >*
+EventsCfg::mutable_items() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.EventsCfg.items)
+  return &items_;
+}
+inline const ::dmi::EventCfg& EventsCfg::items(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.EventsCfg.items)
+  return items_.Get(index);
+}
+inline ::dmi::EventCfg* EventsCfg::add_items() {
+  // @@protoc_insertion_point(field_add:dmi.EventsCfg.items)
+  return items_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg >&
+EventsCfg::items() const {
+  // @@protoc_insertion_point(field_list:dmi.EventsCfg.items)
+  return items_;
+}
+
+// -------------------------------------------------------------------
+
+// ListEventsResponse
+
+// .dmi.Status status = 1;
+inline void ListEventsResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status ListEventsResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.ListEventsResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void ListEventsResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ListEventsResponse.status)
+}
+
+// .dmi.ListEventsResponse.Reason reason = 2;
+inline void ListEventsResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::ListEventsResponse_Reason ListEventsResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.ListEventsResponse.reason)
+  return static_cast< ::dmi::ListEventsResponse_Reason >(reason_);
+}
+inline void ListEventsResponse::set_reason(::dmi::ListEventsResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ListEventsResponse.reason)
+}
+
+// .dmi.EventsCfg events = 3;
+inline bool ListEventsResponse::has_events() const {
+  return this != internal_default_instance() && events_ != nullptr;
+}
+inline void ListEventsResponse::clear_events() {
+  if (GetArenaNoVirtual() == nullptr && events_ != nullptr) {
+    delete events_;
+  }
+  events_ = nullptr;
+}
+inline const ::dmi::EventsCfg& ListEventsResponse::events() const {
+  const ::dmi::EventsCfg* p = events_;
+  // @@protoc_insertion_point(field_get:dmi.ListEventsResponse.events)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::EventsCfg*>(
+      &::dmi::_EventsCfg_default_instance_);
+}
+inline ::dmi::EventsCfg* ListEventsResponse::release_events() {
+  // @@protoc_insertion_point(field_release:dmi.ListEventsResponse.events)
+  
+  ::dmi::EventsCfg* temp = events_;
+  events_ = nullptr;
+  return temp;
+}
+inline ::dmi::EventsCfg* ListEventsResponse::mutable_events() {
+  
+  if (events_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::EventsCfg>(GetArenaNoVirtual());
+    events_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ListEventsResponse.events)
+  return events_;
+}
+inline void ListEventsResponse::set_allocated_events(::dmi::EventsCfg* events) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete events_;
+  }
+  if (events) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      events = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, events, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  events_ = events;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ListEventsResponse.events)
+}
+
+// string reason_detail = 4;
+inline void ListEventsResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ListEventsResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.ListEventsResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void ListEventsResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ListEventsResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void ListEventsResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ListEventsResponse.reason_detail)
+}
+#endif
+inline void ListEventsResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ListEventsResponse.reason_detail)
+}
+inline void ListEventsResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ListEventsResponse.reason_detail)
+}
+inline ::std::string* ListEventsResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ListEventsResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ListEventsResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.ListEventsResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ListEventsResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ListEventsResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// EventsConfigurationRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool EventsConfigurationRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& EventsConfigurationRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* EventsConfigurationRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.EventsConfigurationRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* EventsConfigurationRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.EventsConfigurationRequest.device_uuid)
+  return device_uuid_;
+}
+inline void EventsConfigurationRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventsConfigurationRequest.device_uuid)
+}
+
+// .dmi.EventsCfg changes = 2;
+inline bool EventsConfigurationRequest::has_changes() const {
+  return operation_case() == kChanges;
+}
+inline void EventsConfigurationRequest::set_has_changes() {
+  _oneof_case_[0] = kChanges;
+}
+inline void EventsConfigurationRequest::clear_changes() {
+  if (has_changes()) {
+    delete operation_.changes_;
+    clear_has_operation();
+  }
+}
+inline ::dmi::EventsCfg* EventsConfigurationRequest::release_changes() {
+  // @@protoc_insertion_point(field_release:dmi.EventsConfigurationRequest.changes)
+  if (has_changes()) {
+    clear_has_operation();
+      ::dmi::EventsCfg* temp = operation_.changes_;
+    operation_.changes_ = nullptr;
+    return temp;
+  } else {
+    return nullptr;
+  }
+}
+inline const ::dmi::EventsCfg& EventsConfigurationRequest::changes() const {
+  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationRequest.changes)
+  return has_changes()
+      ? *operation_.changes_
+      : *reinterpret_cast< ::dmi::EventsCfg*>(&::dmi::_EventsCfg_default_instance_);
+}
+inline ::dmi::EventsCfg* EventsConfigurationRequest::mutable_changes() {
+  if (!has_changes()) {
+    clear_operation();
+    set_has_changes();
+    operation_.changes_ = CreateMaybeMessage< ::dmi::EventsCfg >(
+        GetArenaNoVirtual());
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.EventsConfigurationRequest.changes)
+  return operation_.changes_;
+}
+
+// bool reset_to_default = 3;
+inline bool EventsConfigurationRequest::has_reset_to_default() const {
+  return operation_case() == kResetToDefault;
+}
+inline void EventsConfigurationRequest::set_has_reset_to_default() {
+  _oneof_case_[0] = kResetToDefault;
+}
+inline void EventsConfigurationRequest::clear_reset_to_default() {
+  if (has_reset_to_default()) {
+    operation_.reset_to_default_ = false;
+    clear_has_operation();
+  }
+}
+inline bool EventsConfigurationRequest::reset_to_default() const {
+  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationRequest.reset_to_default)
+  if (has_reset_to_default()) {
+    return operation_.reset_to_default_;
+  }
+  return false;
+}
+inline void EventsConfigurationRequest::set_reset_to_default(bool value) {
+  if (!has_reset_to_default()) {
+    clear_operation();
+    set_has_reset_to_default();
+  }
+  operation_.reset_to_default_ = value;
+  // @@protoc_insertion_point(field_set:dmi.EventsConfigurationRequest.reset_to_default)
+}
+
+inline bool EventsConfigurationRequest::has_operation() const {
+  return operation_case() != OPERATION_NOT_SET;
+}
+inline void EventsConfigurationRequest::clear_has_operation() {
+  _oneof_case_[0] = OPERATION_NOT_SET;
+}
+inline EventsConfigurationRequest::OperationCase EventsConfigurationRequest::operation_case() const {
+  return EventsConfigurationRequest::OperationCase(_oneof_case_[0]);
+}
+// -------------------------------------------------------------------
+
+// EventsConfigurationResponse
+
+// .dmi.Status status = 1;
+inline void EventsConfigurationResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status EventsConfigurationResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void EventsConfigurationResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.EventsConfigurationResponse.status)
+}
+
+// .dmi.EventsConfigurationResponse.Reason reason = 2;
+inline void EventsConfigurationResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::EventsConfigurationResponse_Reason EventsConfigurationResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationResponse.reason)
+  return static_cast< ::dmi::EventsConfigurationResponse_Reason >(reason_);
+}
+inline void EventsConfigurationResponse::set_reason(::dmi::EventsConfigurationResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.EventsConfigurationResponse.reason)
+}
+
+// string reason_detail = 3;
+inline void EventsConfigurationResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& EventsConfigurationResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void EventsConfigurationResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.EventsConfigurationResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void EventsConfigurationResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.EventsConfigurationResponse.reason_detail)
+}
+#endif
+inline void EventsConfigurationResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.EventsConfigurationResponse.reason_detail)
+}
+inline void EventsConfigurationResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.EventsConfigurationResponse.reason_detail)
+}
+inline ::std::string* EventsConfigurationResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.EventsConfigurationResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* EventsConfigurationResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.EventsConfigurationResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void EventsConfigurationResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventsConfigurationResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// EventMetaData
+
+// .dmi.Uuid device_uuid = 1;
+inline bool EventMetaData::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& EventMetaData::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.EventMetaData.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* EventMetaData::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.EventMetaData.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* EventMetaData::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.EventMetaData.device_uuid)
+  return device_uuid_;
+}
+inline void EventMetaData::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventMetaData.device_uuid)
+}
+
+// .dmi.Uuid component_uuid = 2;
+inline bool EventMetaData::has_component_uuid() const {
+  return this != internal_default_instance() && component_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& EventMetaData::component_uuid() const {
+  const ::dmi::Uuid* p = component_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.EventMetaData.component_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* EventMetaData::release_component_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.EventMetaData.component_uuid)
+  
+  ::dmi::Uuid* temp = component_uuid_;
+  component_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* EventMetaData::mutable_component_uuid() {
+  
+  if (component_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    component_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.EventMetaData.component_uuid)
+  return component_uuid_;
+}
+inline void EventMetaData::set_allocated_component_uuid(::dmi::Uuid* component_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(component_uuid_);
+  }
+  if (component_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      component_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, component_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  component_uuid_ = component_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventMetaData.component_uuid)
+}
+
+// string component_name = 3;
+inline void EventMetaData::clear_component_name() {
+  component_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& EventMetaData::component_name() const {
+  // @@protoc_insertion_point(field_get:dmi.EventMetaData.component_name)
+  return component_name_.GetNoArena();
+}
+inline void EventMetaData::set_component_name(const ::std::string& value) {
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.EventMetaData.component_name)
+}
+#if LANG_CXX11
+inline void EventMetaData::set_component_name(::std::string&& value) {
+  
+  component_name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.EventMetaData.component_name)
+}
+#endif
+inline void EventMetaData::set_component_name(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.EventMetaData.component_name)
+}
+inline void EventMetaData::set_component_name(const char* value, size_t size) {
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.EventMetaData.component_name)
+}
+inline ::std::string* EventMetaData::mutable_component_name() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.EventMetaData.component_name)
+  return component_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* EventMetaData::release_component_name() {
+  // @@protoc_insertion_point(field_release:dmi.EventMetaData.component_name)
+  
+  return component_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void EventMetaData::set_allocated_component_name(::std::string* component_name) {
+  if (component_name != nullptr) {
+    
+  } else {
+    
+  }
+  component_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), component_name);
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventMetaData.component_name)
+}
+
+// -------------------------------------------------------------------
+
+// Event
+
+// .dmi.EventMetaData event_metadata = 1;
+inline bool Event::has_event_metadata() const {
+  return this != internal_default_instance() && event_metadata_ != nullptr;
+}
+inline void Event::clear_event_metadata() {
+  if (GetArenaNoVirtual() == nullptr && event_metadata_ != nullptr) {
+    delete event_metadata_;
+  }
+  event_metadata_ = nullptr;
+}
+inline const ::dmi::EventMetaData& Event::event_metadata() const {
+  const ::dmi::EventMetaData* p = event_metadata_;
+  // @@protoc_insertion_point(field_get:dmi.Event.event_metadata)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::EventMetaData*>(
+      &::dmi::_EventMetaData_default_instance_);
+}
+inline ::dmi::EventMetaData* Event::release_event_metadata() {
+  // @@protoc_insertion_point(field_release:dmi.Event.event_metadata)
+  
+  ::dmi::EventMetaData* temp = event_metadata_;
+  event_metadata_ = nullptr;
+  return temp;
+}
+inline ::dmi::EventMetaData* Event::mutable_event_metadata() {
+  
+  if (event_metadata_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::EventMetaData>(GetArenaNoVirtual());
+    event_metadata_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Event.event_metadata)
+  return event_metadata_;
+}
+inline void Event::set_allocated_event_metadata(::dmi::EventMetaData* event_metadata) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete event_metadata_;
+  }
+  if (event_metadata) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      event_metadata = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, event_metadata, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  event_metadata_ = event_metadata;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Event.event_metadata)
+}
+
+// .dmi.EventIds event_id = 2;
+inline void Event::clear_event_id() {
+  event_id_ = 0;
+}
+inline ::dmi::EventIds Event::event_id() const {
+  // @@protoc_insertion_point(field_get:dmi.Event.event_id)
+  return static_cast< ::dmi::EventIds >(event_id_);
+}
+inline void Event::set_event_id(::dmi::EventIds value) {
+  
+  event_id_ = value;
+  // @@protoc_insertion_point(field_set:dmi.Event.event_id)
+}
+
+// .google.protobuf.Timestamp raised_ts = 3;
+inline bool Event::has_raised_ts() const {
+  return this != internal_default_instance() && raised_ts_ != nullptr;
+}
+inline const ::google::protobuf::Timestamp& Event::raised_ts() const {
+  const ::google::protobuf::Timestamp* p = raised_ts_;
+  // @@protoc_insertion_point(field_get:dmi.Event.raised_ts)
+  return p != nullptr ? *p : *reinterpret_cast<const ::google::protobuf::Timestamp*>(
+      &::google::protobuf::_Timestamp_default_instance_);
+}
+inline ::google::protobuf::Timestamp* Event::release_raised_ts() {
+  // @@protoc_insertion_point(field_release:dmi.Event.raised_ts)
+  
+  ::google::protobuf::Timestamp* temp = raised_ts_;
+  raised_ts_ = nullptr;
+  return temp;
+}
+inline ::google::protobuf::Timestamp* Event::mutable_raised_ts() {
+  
+  if (raised_ts_ == nullptr) {
+    auto* p = CreateMaybeMessage<::google::protobuf::Timestamp>(GetArenaNoVirtual());
+    raised_ts_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Event.raised_ts)
+  return raised_ts_;
+}
+inline void Event::set_allocated_raised_ts(::google::protobuf::Timestamp* raised_ts) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(raised_ts_);
+  }
+  if (raised_ts) {
+    ::google::protobuf::Arena* submessage_arena =
+      reinterpret_cast<::google::protobuf::MessageLite*>(raised_ts)->GetArena();
+    if (message_arena != submessage_arena) {
+      raised_ts = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, raised_ts, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  raised_ts_ = raised_ts;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Event.raised_ts)
+}
+
+// .dmi.ThresholdInformation threshold_info = 4;
+inline bool Event::has_threshold_info() const {
+  return this != internal_default_instance() && threshold_info_ != nullptr;
+}
+inline void Event::clear_threshold_info() {
+  if (GetArenaNoVirtual() == nullptr && threshold_info_ != nullptr) {
+    delete threshold_info_;
+  }
+  threshold_info_ = nullptr;
+}
+inline const ::dmi::ThresholdInformation& Event::threshold_info() const {
+  const ::dmi::ThresholdInformation* p = threshold_info_;
+  // @@protoc_insertion_point(field_get:dmi.Event.threshold_info)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ThresholdInformation*>(
+      &::dmi::_ThresholdInformation_default_instance_);
+}
+inline ::dmi::ThresholdInformation* Event::release_threshold_info() {
+  // @@protoc_insertion_point(field_release:dmi.Event.threshold_info)
+  
+  ::dmi::ThresholdInformation* temp = threshold_info_;
+  threshold_info_ = nullptr;
+  return temp;
+}
+inline ::dmi::ThresholdInformation* Event::mutable_threshold_info() {
+  
+  if (threshold_info_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ThresholdInformation>(GetArenaNoVirtual());
+    threshold_info_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Event.threshold_info)
+  return threshold_info_;
+}
+inline void Event::set_allocated_threshold_info(::dmi::ThresholdInformation* threshold_info) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete threshold_info_;
+  }
+  if (threshold_info) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      threshold_info = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, threshold_info, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  threshold_info_ = threshold_info;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Event.threshold_info)
+}
+
+// string add_info = 5;
+inline void Event::clear_add_info() {
+  add_info_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Event::add_info() const {
+  // @@protoc_insertion_point(field_get:dmi.Event.add_info)
+  return add_info_.GetNoArena();
+}
+inline void Event::set_add_info(const ::std::string& value) {
+  
+  add_info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Event.add_info)
+}
+#if LANG_CXX11
+inline void Event::set_add_info(::std::string&& value) {
+  
+  add_info_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Event.add_info)
+}
+#endif
+inline void Event::set_add_info(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  add_info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Event.add_info)
+}
+inline void Event::set_add_info(const char* value, size_t size) {
+  
+  add_info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Event.add_info)
+}
+inline ::std::string* Event::mutable_add_info() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Event.add_info)
+  return add_info_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Event::release_add_info() {
+  // @@protoc_insertion_point(field_release:dmi.Event.add_info)
+  
+  return add_info_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Event::set_allocated_add_info(::std::string* add_info) {
+  if (add_info != nullptr) {
+    
+  } else {
+    
+  }
+  add_info_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), add_info);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Event.add_info)
+}
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace dmi
+
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::dmi::ListEventsResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ListEventsResponse_Reason>() {
+  return ::dmi::ListEventsResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::EventsConfigurationResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::EventsConfigurationResponse_Reason>() {
+  return ::dmi::EventsConfigurationResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::EventIds> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::EventIds>() {
+  return ::dmi::EventIds_descriptor();
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#include <google/protobuf/port_undef.inc>
+#endif  // PROTOBUF_INCLUDED_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto
diff --git a/cpp/dmi/hw_management_service.pb.cc b/cpp/dmi/hw_management_service.pb.cc
new file mode 100644
index 0000000..573645e
--- /dev/null
+++ b/cpp/dmi/hw_management_service.pb.cc
@@ -0,0 +1,10197 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/hw_management_service.proto
+
+#include "dmi/hw_management_service.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Uuid_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<2> scc_info_Hardware_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<2> scc_info_ModifiableComponent_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<9> scc_info_Component_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmanagement_5fservice_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_EntitiesLogLevel_dmi_2fhw_5fmanagement_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmanagement_5fservice_2eproto ::google::protobuf::internal::SCCInfo<2> scc_info_ManagedDeviceInfo_dmi_2fhw_5fmanagement_5fservice_2eproto;
+namespace dmi {
+class PhysicalInventoryRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<PhysicalInventoryRequest> _instance;
+} _PhysicalInventoryRequest_default_instance_;
+class PhysicalInventoryResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<PhysicalInventoryResponse> _instance;
+} _PhysicalInventoryResponse_default_instance_;
+class HWComponentInfoGetRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<HWComponentInfoGetRequest> _instance;
+} _HWComponentInfoGetRequest_default_instance_;
+class HWComponentInfoGetResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<HWComponentInfoGetResponse> _instance;
+} _HWComponentInfoGetResponse_default_instance_;
+class HWComponentInfoSetRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<HWComponentInfoSetRequest> _instance;
+} _HWComponentInfoSetRequest_default_instance_;
+class HWComponentInfoSetResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<HWComponentInfoSetResponse> _instance;
+} _HWComponentInfoSetResponse_default_instance_;
+class StartManagingDeviceResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<StartManagingDeviceResponse> _instance;
+} _StartManagingDeviceResponse_default_instance_;
+class StopManagingDeviceRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<StopManagingDeviceRequest> _instance;
+} _StopManagingDeviceRequest_default_instance_;
+class StopManagingDeviceResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<StopManagingDeviceResponse> _instance;
+} _StopManagingDeviceResponse_default_instance_;
+class ManagedDeviceInfoDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ManagedDeviceInfo> _instance;
+} _ManagedDeviceInfo_default_instance_;
+class ManagedDevicesResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ManagedDevicesResponse> _instance;
+} _ManagedDevicesResponse_default_instance_;
+class SetLoggingEndpointRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<SetLoggingEndpointRequest> _instance;
+} _SetLoggingEndpointRequest_default_instance_;
+class SetRemoteEndpointResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<SetRemoteEndpointResponse> _instance;
+} _SetRemoteEndpointResponse_default_instance_;
+class GetLoggingEndpointResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<GetLoggingEndpointResponse> _instance;
+} _GetLoggingEndpointResponse_default_instance_;
+class SetMsgBusEndpointRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<SetMsgBusEndpointRequest> _instance;
+} _SetMsgBusEndpointRequest_default_instance_;
+class GetMsgBusEndpointResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<GetMsgBusEndpointResponse> _instance;
+} _GetMsgBusEndpointResponse_default_instance_;
+class EntitiesLogLevelDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<EntitiesLogLevel> _instance;
+} _EntitiesLogLevel_default_instance_;
+class SetLogLevelRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<SetLogLevelRequest> _instance;
+} _SetLogLevelRequest_default_instance_;
+class SetLogLevelResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<SetLogLevelResponse> _instance;
+} _SetLogLevelResponse_default_instance_;
+class GetLogLevelRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<GetLogLevelRequest> _instance;
+} _GetLogLevelRequest_default_instance_;
+class GetLogLevelResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<GetLogLevelResponse> _instance;
+} _GetLogLevelResponse_default_instance_;
+class GetLoggableEntitiesRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<GetLoggableEntitiesRequest> _instance;
+} _GetLoggableEntitiesRequest_default_instance_;
+}  // namespace dmi
+static void InitDefaultsPhysicalInventoryRequest_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_PhysicalInventoryRequest_default_instance_;
+    new (ptr) ::dmi::PhysicalInventoryRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::PhysicalInventoryRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_PhysicalInventoryRequest_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsPhysicalInventoryRequest_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsPhysicalInventoryResponse_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_PhysicalInventoryResponse_default_instance_;
+    new (ptr) ::dmi::PhysicalInventoryResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::PhysicalInventoryResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_PhysicalInventoryResponse_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsPhysicalInventoryResponse_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Hardware_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsHWComponentInfoGetRequest_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_HWComponentInfoGetRequest_default_instance_;
+    new (ptr) ::dmi::HWComponentInfoGetRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::HWComponentInfoGetRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_HWComponentInfoGetRequest_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsHWComponentInfoGetRequest_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsHWComponentInfoGetResponse_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_HWComponentInfoGetResponse_default_instance_;
+    new (ptr) ::dmi::HWComponentInfoGetResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::HWComponentInfoGetResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_HWComponentInfoGetResponse_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsHWComponentInfoGetResponse_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Component_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsHWComponentInfoSetRequest_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_HWComponentInfoSetRequest_default_instance_;
+    new (ptr) ::dmi::HWComponentInfoSetRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::HWComponentInfoSetRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_HWComponentInfoSetRequest_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsHWComponentInfoSetRequest_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,
+      &scc_info_ModifiableComponent_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsHWComponentInfoSetResponse_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_HWComponentInfoSetResponse_default_instance_;
+    new (ptr) ::dmi::HWComponentInfoSetResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::HWComponentInfoSetResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_HWComponentInfoSetResponse_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsHWComponentInfoSetResponse_dmi_2fhw_5fmanagement_5fservice_2eproto}, {}};
+
+static void InitDefaultsStartManagingDeviceResponse_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_StartManagingDeviceResponse_default_instance_;
+    new (ptr) ::dmi::StartManagingDeviceResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::StartManagingDeviceResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_StartManagingDeviceResponse_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsStartManagingDeviceResponse_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsStopManagingDeviceRequest_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_StopManagingDeviceRequest_default_instance_;
+    new (ptr) ::dmi::StopManagingDeviceRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::StopManagingDeviceRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_StopManagingDeviceRequest_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsStopManagingDeviceRequest_dmi_2fhw_5fmanagement_5fservice_2eproto}, {}};
+
+static void InitDefaultsStopManagingDeviceResponse_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_StopManagingDeviceResponse_default_instance_;
+    new (ptr) ::dmi::StopManagingDeviceResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::StopManagingDeviceResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_StopManagingDeviceResponse_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsStopManagingDeviceResponse_dmi_2fhw_5fmanagement_5fservice_2eproto}, {}};
+
+static void InitDefaultsManagedDeviceInfo_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ManagedDeviceInfo_default_instance_;
+    new (ptr) ::dmi::ManagedDeviceInfo();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ManagedDeviceInfo::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_ManagedDeviceInfo_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsManagedDeviceInfo_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_ModifiableComponent_dmi_2fhw_2eproto.base,
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsManagedDevicesResponse_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ManagedDevicesResponse_default_instance_;
+    new (ptr) ::dmi::ManagedDevicesResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ManagedDevicesResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_ManagedDevicesResponse_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsManagedDevicesResponse_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_ManagedDeviceInfo_dmi_2fhw_5fmanagement_5fservice_2eproto.base,}};
+
+static void InitDefaultsSetLoggingEndpointRequest_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_SetLoggingEndpointRequest_default_instance_;
+    new (ptr) ::dmi::SetLoggingEndpointRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::SetLoggingEndpointRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_SetLoggingEndpointRequest_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsSetLoggingEndpointRequest_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsSetRemoteEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_SetRemoteEndpointResponse_default_instance_;
+    new (ptr) ::dmi::SetRemoteEndpointResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::SetRemoteEndpointResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_SetRemoteEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsSetRemoteEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto}, {}};
+
+static void InitDefaultsGetLoggingEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_GetLoggingEndpointResponse_default_instance_;
+    new (ptr) ::dmi::GetLoggingEndpointResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::GetLoggingEndpointResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_GetLoggingEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsGetLoggingEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto}, {}};
+
+static void InitDefaultsSetMsgBusEndpointRequest_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_SetMsgBusEndpointRequest_default_instance_;
+    new (ptr) ::dmi::SetMsgBusEndpointRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::SetMsgBusEndpointRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_SetMsgBusEndpointRequest_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsSetMsgBusEndpointRequest_dmi_2fhw_5fmanagement_5fservice_2eproto}, {}};
+
+static void InitDefaultsGetMsgBusEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_GetMsgBusEndpointResponse_default_instance_;
+    new (ptr) ::dmi::GetMsgBusEndpointResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::GetMsgBusEndpointResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_GetMsgBusEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsGetMsgBusEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto}, {}};
+
+static void InitDefaultsEntitiesLogLevel_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_EntitiesLogLevel_default_instance_;
+    new (ptr) ::dmi::EntitiesLogLevel();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::EntitiesLogLevel::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_EntitiesLogLevel_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsEntitiesLogLevel_dmi_2fhw_5fmanagement_5fservice_2eproto}, {}};
+
+static void InitDefaultsSetLogLevelRequest_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_SetLogLevelRequest_default_instance_;
+    new (ptr) ::dmi::SetLogLevelRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::SetLogLevelRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_SetLogLevelRequest_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsSetLogLevelRequest_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,
+      &scc_info_EntitiesLogLevel_dmi_2fhw_5fmanagement_5fservice_2eproto.base,}};
+
+static void InitDefaultsSetLogLevelResponse_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_SetLogLevelResponse_default_instance_;
+    new (ptr) ::dmi::SetLogLevelResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::SetLogLevelResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_SetLogLevelResponse_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsSetLogLevelResponse_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsGetLogLevelRequest_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_GetLogLevelRequest_default_instance_;
+    new (ptr) ::dmi::GetLogLevelRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::GetLogLevelRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_GetLogLevelRequest_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsGetLogLevelRequest_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsGetLogLevelResponse_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_GetLogLevelResponse_default_instance_;
+    new (ptr) ::dmi::GetLogLevelResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::GetLogLevelResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_GetLogLevelResponse_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsGetLogLevelResponse_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,
+      &scc_info_EntitiesLogLevel_dmi_2fhw_5fmanagement_5fservice_2eproto.base,}};
+
+static void InitDefaultsGetLoggableEntitiesRequest_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_GetLoggableEntitiesRequest_default_instance_;
+    new (ptr) ::dmi::GetLoggableEntitiesRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::GetLoggableEntitiesRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_GetLoggableEntitiesRequest_dmi_2fhw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsGetLoggableEntitiesRequest_dmi_2fhw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+void InitDefaults_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  ::google::protobuf::internal::InitSCC(&scc_info_PhysicalInventoryRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_PhysicalInventoryResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_HWComponentInfoGetRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_HWComponentInfoGetResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_HWComponentInfoSetRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_HWComponentInfoSetResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_StartManagingDeviceResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_StopManagingDeviceRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_StopManagingDeviceResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ManagedDeviceInfo_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ManagedDevicesResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_SetLoggingEndpointRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_SetRemoteEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_GetLoggingEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_SetMsgBusEndpointRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_GetMsgBusEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_EntitiesLogLevel_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_SetLogLevelRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_SetLogLevelResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_GetLogLevelRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_GetLogLevelResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_GetLoggableEntitiesRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+}
+
+::google::protobuf::Metadata file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[22];
+const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto[11];
+constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto = nullptr;
+
+const ::google::protobuf::uint32 TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::PhysicalInventoryRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::PhysicalInventoryRequest, device_uuid_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::PhysicalInventoryResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::PhysicalInventoryResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::PhysicalInventoryResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::PhysicalInventoryResponse, inventory_),
+  PROTOBUF_FIELD_OFFSET(::dmi::PhysicalInventoryResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoGetRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoGetRequest, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoGetRequest, component_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoGetRequest, component_name_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoGetResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoGetResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoGetResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoGetResponse, component_),
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoGetResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoSetRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoSetRequest, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoSetRequest, component_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoSetRequest, component_name_),
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoSetRequest, changes_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoSetResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoSetResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoSetResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::HWComponentInfoSetResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::StartManagingDeviceResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::StartManagingDeviceResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::StartManagingDeviceResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::StartManagingDeviceResponse, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::StartManagingDeviceResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::StopManagingDeviceRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::StopManagingDeviceRequest, name_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::StopManagingDeviceResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::StopManagingDeviceResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::StopManagingDeviceResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::StopManagingDeviceResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ManagedDeviceInfo, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ManagedDeviceInfo, info_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ManagedDeviceInfo, device_uuid_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ManagedDevicesResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ManagedDevicesResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ManagedDevicesResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ManagedDevicesResponse, devices_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::SetLoggingEndpointRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::SetLoggingEndpointRequest, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::SetLoggingEndpointRequest, logging_endpoint_),
+  PROTOBUF_FIELD_OFFSET(::dmi::SetLoggingEndpointRequest, logging_protocol_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::SetRemoteEndpointResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::SetRemoteEndpointResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::SetRemoteEndpointResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::SetRemoteEndpointResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLoggingEndpointResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLoggingEndpointResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLoggingEndpointResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLoggingEndpointResponse, logging_endpoint_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLoggingEndpointResponse, logging_protocol_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLoggingEndpointResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::SetMsgBusEndpointRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::SetMsgBusEndpointRequest, msgbus_endpoint_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMsgBusEndpointResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMsgBusEndpointResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMsgBusEndpointResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMsgBusEndpointResponse, msgbus_endpoint_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMsgBusEndpointResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::EntitiesLogLevel, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::EntitiesLogLevel, loglevel_),
+  PROTOBUF_FIELD_OFFSET(::dmi::EntitiesLogLevel, entities_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::SetLogLevelRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::SetLogLevelRequest, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::SetLogLevelRequest, loglevels_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::SetLogLevelResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::SetLogLevelResponse, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::SetLogLevelResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::SetLogLevelResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::SetLogLevelResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLogLevelRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLogLevelRequest, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLogLevelRequest, entities_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLogLevelResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLogLevelResponse, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLogLevelResponse, loglevels_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLogLevelResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLogLevelResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLogLevelResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLoggableEntitiesRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetLoggableEntitiesRequest, device_uuid_),
+};
+static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, -1, sizeof(::dmi::PhysicalInventoryRequest)},
+  { 6, -1, sizeof(::dmi::PhysicalInventoryResponse)},
+  { 15, -1, sizeof(::dmi::HWComponentInfoGetRequest)},
+  { 23, -1, sizeof(::dmi::HWComponentInfoGetResponse)},
+  { 32, -1, sizeof(::dmi::HWComponentInfoSetRequest)},
+  { 41, -1, sizeof(::dmi::HWComponentInfoSetResponse)},
+  { 49, -1, sizeof(::dmi::StartManagingDeviceResponse)},
+  { 58, -1, sizeof(::dmi::StopManagingDeviceRequest)},
+  { 64, -1, sizeof(::dmi::StopManagingDeviceResponse)},
+  { 72, -1, sizeof(::dmi::ManagedDeviceInfo)},
+  { 79, -1, sizeof(::dmi::ManagedDevicesResponse)},
+  { 87, -1, sizeof(::dmi::SetLoggingEndpointRequest)},
+  { 95, -1, sizeof(::dmi::SetRemoteEndpointResponse)},
+  { 103, -1, sizeof(::dmi::GetLoggingEndpointResponse)},
+  { 113, -1, sizeof(::dmi::SetMsgBusEndpointRequest)},
+  { 119, -1, sizeof(::dmi::GetMsgBusEndpointResponse)},
+  { 128, -1, sizeof(::dmi::EntitiesLogLevel)},
+  { 135, -1, sizeof(::dmi::SetLogLevelRequest)},
+  { 142, -1, sizeof(::dmi::SetLogLevelResponse)},
+  { 151, -1, sizeof(::dmi::GetLogLevelRequest)},
+  { 158, -1, sizeof(::dmi::GetLogLevelResponse)},
+  { 168, -1, sizeof(::dmi::GetLoggableEntitiesRequest)},
+};
+
+static ::google::protobuf::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_PhysicalInventoryRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_PhysicalInventoryResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_HWComponentInfoGetRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_HWComponentInfoGetResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_HWComponentInfoSetRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_HWComponentInfoSetResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_StartManagingDeviceResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_StopManagingDeviceRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_StopManagingDeviceResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ManagedDeviceInfo_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ManagedDevicesResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_SetLoggingEndpointRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_SetRemoteEndpointResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetLoggingEndpointResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_SetMsgBusEndpointRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetMsgBusEndpointResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_EntitiesLogLevel_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_SetLogLevelRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_SetLogLevelResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetLogLevelRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetLogLevelResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetLoggableEntitiesRequest_default_instance_),
+};
+
+::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto = {
+  {}, AddDescriptors_dmi_2fhw_5fmanagement_5fservice_2eproto, "dmi/hw_management_service.proto", schemas,
+  file_default_instances, TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto::offsets,
+  file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto, 22, file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto, file_level_service_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto,
+};
+
+const char descriptor_table_protodef_dmi_2fhw_5fmanagement_5fservice_2eproto[] =
+  "\n\037dmi/hw_management_service.proto\022\003dmi\032\021"
+  "dmi/commons.proto\032\014dmi/hw.proto\032\033google/"
+  "protobuf/empty.proto\":\n\030PhysicalInventor"
+  "yRequest\022\036\n\013device_uuid\030\001 \001(\0132\t.dmi.Uuid"
+  "\"\210\002\n\031PhysicalInventoryResponse\022\033\n\006status"
+  "\030\001 \001(\0162\013.dmi.Status\0225\n\006reason\030\002 \001(\0162%.dm"
+  "i.PhysicalInventoryResponse.Reason\022 \n\tin"
+  "ventory\030\003 \001(\0132\r.dmi.Hardware\022\025\n\rreason_d"
+  "etail\030\004 \001(\t\"^\n\006Reason\022\024\n\020UNDEFINED_REASO"
+  "N\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERNAL_ERRO"
+  "R\020\002\022\026\n\022DEVICE_UNREACHABLE\020\003\"v\n\031HWCompone"
+  "ntInfoGetRequest\022\036\n\013device_uuid\030\001 \001(\0132\t."
+  "dmi.Uuid\022!\n\016component_uuid\030\002 \001(\0132\t.dmi.U"
+  "uid\022\026\n\016component_name\030\003 \001(\t\"\242\002\n\032HWCompon"
+  "entInfoGetResponse\022\033\n\006status\030\001 \001(\0162\013.dmi"
+  ".Status\0226\n\006reason\030\002 \001(\0162&.dmi.HWComponen"
+  "tInfoGetResponse.Reason\022!\n\tcomponent\030\003 \001"
+  "(\0132\016.dmi.Component\022\025\n\rreason_detail\030\004 \001("
+  "\t\"u\n\006Reason\022\024\n\020UNDEFINED_REASON\020\000\022\022\n\016UNK"
+  "NOWN_DEVICE\020\001\022\025\n\021UNKNOWN_COMPONENT\020\002\022\022\n\016"
+  "INTERNAL_ERROR\020\003\022\026\n\022DEVICE_UNREACHABLE\020\004"
+  "\"\241\001\n\031HWComponentInfoSetRequest\022\036\n\013device"
+  "_uuid\030\001 \001(\0132\t.dmi.Uuid\022!\n\016component_uuid"
+  "\030\002 \001(\0132\t.dmi.Uuid\022\026\n\016component_name\030\003 \001("
+  "\t\022)\n\007changes\030\004 \001(\0132\030.dmi.ModifiableCompo"
+  "nent\"\224\002\n\032HWComponentInfoSetResponse\022\033\n\006s"
+  "tatus\030\001 \001(\0162\013.dmi.Status\0226\n\006reason\030\002 \001(\016"
+  "2&.dmi.HWComponentInfoSetResponse.Reason"
+  "\022\025\n\rreason_detail\030\003 \001(\t\"\211\001\n\006Reason\022\024\n\020UN"
+  "DEFINED_REASON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\025\n\021"
+  "UNKNOWN_COMPONENT\020\002\022\022\n\016INVALID_PARAMS\020\003\022"
+  "\022\n\016INTERNAL_ERROR\020\004\022\026\n\022DEVICE_UNREACHABL"
+  "E\020\005\"\262\002\n\033StartManagingDeviceResponse\022\033\n\006s"
+  "tatus\030\001 \001(\0162\013.dmi.Status\0227\n\006reason\030\002 \001(\016"
+  "2\'.dmi.StartManagingDeviceResponse.Reaso"
+  "n\022\036\n\013device_uuid\030\003 \001(\0132\t.dmi.Uuid\022\025\n\rrea"
+  "son_detail\030\004 \001(\t\"\205\001\n\006Reason\022\024\n\020UNDEFINED"
+  "_REASON\020\000\022\032\n\026DEVICE_ALREADY_MANAGED\020\001\022!\n"
+  "\035OPERATION_ALREADY_IN_PROGRESS\020\002\022\022\n\016INVA"
+  "LID_PARAMS\020\003\022\022\n\016INTERNAL_ERROR\020\004\")\n\031Stop"
+  "ManagingDeviceRequest\022\014\n\004name\030\001 \001(\t\"\274\001\n\032"
+  "StopManagingDeviceResponse\022\033\n\006status\030\001 \001"
+  "(\0162\013.dmi.Status\0226\n\006reason\030\002 \001(\0162&.dmi.St"
+  "opManagingDeviceResponse.Reason\022\025\n\rreaso"
+  "n_detail\030\003 \001(\t\"2\n\006Reason\022\024\n\020UNDEFINED_RE"
+  "ASON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\"[\n\021ManagedDev"
+  "iceInfo\022&\n\004info\030\001 \001(\0132\030.dmi.ModifiableCo"
+  "mponent\022\036\n\013device_uuid\030\002 \001(\0132\t.dmi.Uuid\""
+  "\306\001\n\026ManagedDevicesResponse\022\033\n\006status\030\001 \001"
+  "(\0162\013.dmi.Status\0222\n\006reason\030\002 \001(\0162\".dmi.Ma"
+  "nagedDevicesResponse.Reason\022\'\n\007devices\030\003"
+  " \003(\0132\026.dmi.ManagedDeviceInfo\"2\n\006Reason\022\024"
+  "\n\020UNDEFINED_REASON\020\000\022\022\n\016INTERNAL_ERROR\020\001"
+  "\"o\n\031SetLoggingEndpointRequest\022\036\n\013device_"
+  "uuid\030\001 \001(\0132\t.dmi.Uuid\022\030\n\020logging_endpoin"
+  "t\030\002 \001(\t\022\030\n\020logging_protocol\030\003 \001(\t\"\303\002\n\031Se"
+  "tRemoteEndpointResponse\022\033\n\006status\030\001 \001(\0162"
+  "\013.dmi.Status\0225\n\006reason\030\002 \001(\0162%.dmi.SetRe"
+  "moteEndpointResponse.Reason\022\025\n\rreason_de"
+  "tail\030\003 \001(\t\"\272\001\n\006Reason\022\024\n\020UNDEFINED_REASO"
+  "N\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERNAL_ERRO"
+  "R\020\002\022\032\n\026LOGGING_ENDPOINT_ERROR\020\003\022#\n\037LOGGI"
+  "NG_ENDPOINT_PROTOCOL_ERROR\020\004\022\031\n\025MSGBUS_E"
+  "NDPOINT_ERROR\020\005\022\026\n\022DEVICE_UNREACHABLE\020\006\""
+  "\234\002\n\032GetLoggingEndpointResponse\022\033\n\006status"
+  "\030\001 \001(\0162\013.dmi.Status\0226\n\006reason\030\002 \001(\0162&.dm"
+  "i.GetLoggingEndpointResponse.Reason\022\030\n\020l"
+  "ogging_endpoint\030\003 \001(\t\022\030\n\020logging_protoco"
+  "l\030\004 \001(\t\022\025\n\rreason_detail\030\005 \001(\t\"^\n\006Reason"
+  "\022\024\n\020UNDEFINED_REASON\020\000\022\022\n\016UNKNOWN_DEVICE"
+  "\020\001\022\022\n\016INTERNAL_ERROR\020\002\022\026\n\022DEVICE_UNREACH"
+  "ABLE\020\003\"3\n\030SetMsgBusEndpointRequest\022\027\n\017ms"
+  "gbus_endpoint\030\001 \001(\t\"\353\001\n\031GetMsgBusEndpoin"
+  "tResponse\022\033\n\006status\030\001 \001(\0162\013.dmi.Status\0225"
+  "\n\006reason\030\002 \001(\0162%.dmi.GetMsgBusEndpointRe"
+  "sponse.Reason\022\027\n\017msgbus_endpoint\030\003 \001(\t\022\025"
+  "\n\rreason_detail\030\004 \001(\t\"J\n\006Reason\022\024\n\020UNDEF"
+  "INED_REASON\020\000\022\022\n\016INTERNAL_ERROR\020\001\022\026\n\022DEV"
+  "ICE_UNREACHABLE\020\002\"E\n\020EntitiesLogLevel\022\037\n"
+  "\010logLevel\030\001 \001(\0162\r.dmi.LogLevel\022\020\n\010entiti"
+  "es\030\002 \003(\t\"^\n\022SetLogLevelRequest\022\036\n\013device"
+  "_uuid\030\001 \001(\0132\t.dmi.Uuid\022(\n\tloglevels\030\002 \003("
+  "\0132\025.dmi.EntitiesLogLevel\"\222\002\n\023SetLogLevel"
+  "Response\022\036\n\013device_uuid\030\001 \001(\0132\t.dmi.Uuid"
+  "\022\033\n\006status\030\002 \001(\0162\013.dmi.Status\022/\n\006reason\030"
+  "\003 \001(\0162\037.dmi.SetLogLevelResponse.Reason\022\025"
+  "\n\rreason_detail\030\004 \001(\t\"v\n\006Reason\022\024\n\020UNDEF"
+  "INED_REASON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INT"
+  "ERNAL_ERROR\020\002\022\026\n\022UNKNOWN_LOG_ENTITY\020\003\022\026\n"
+  "\022DEVICE_UNREACHABLE\020\004\"F\n\022GetLogLevelRequ"
+  "est\022\036\n\013device_uuid\030\001 \001(\0132\t.dmi.Uuid\022\020\n\010e"
+  "ntities\030\002 \003(\t\"\274\002\n\023GetLogLevelResponse\022\036\n"
+  "\013device_uuid\030\001 \001(\0132\t.dmi.Uuid\022(\n\tlogLeve"
+  "ls\030\002 \003(\0132\025.dmi.EntitiesLogLevel\022\033\n\006statu"
+  "s\030\003 \001(\0162\013.dmi.Status\022/\n\006reason\030\004 \001(\0162\037.d"
+  "mi.GetLogLevelResponse.Reason\022\025\n\rreason_"
+  "detail\030\005 \001(\t\"v\n\006Reason\022\024\n\020UNDEFINED_REAS"
+  "ON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERNAL_ERR"
+  "OR\020\002\022\026\n\022UNKNOWN_LOG_ENTITY\020\003\022\026\n\022DEVICE_U"
+  "NREACHABLE\020\004\"<\n\032GetLoggableEntitiesReque"
+  "st\022\036\n\013device_uuid\030\001 \001(\0132\t.dmi.Uuid2\257\010\n\031N"
+  "ativeHWManagementService\022S\n\023StartManagin"
+  "gDevice\022\030.dmi.ModifiableComponent\032 .dmi."
+  "StartManagingDeviceResponse0\001\022U\n\022StopMan"
+  "agingDevice\022\036.dmi.StopManagingDeviceRequ"
+  "est\032\037.dmi.StopManagingDeviceResponse\022H\n\021"
+  "GetManagedDevices\022\026.google.protobuf.Empt"
+  "y\032\033.dmi.ManagedDevicesResponse\022W\n\024GetPhy"
+  "sicalInventory\022\035.dmi.PhysicalInventoryRe"
+  "quest\032\036.dmi.PhysicalInventoryResponse0\001\022"
+  "W\n\022GetHWComponentInfo\022\036.dmi.HWComponentI"
+  "nfoGetRequest\032\037.dmi.HWComponentInfoGetRe"
+  "sponse0\001\022U\n\022SetHWComponentInfo\022\036.dmi.HWC"
+  "omponentInfoSetRequest\032\037.dmi.HWComponent"
+  "InfoSetResponse\022T\n\022SetLoggingEndpoint\022\036."
+  "dmi.SetLoggingEndpointRequest\032\036.dmi.SetR"
+  "emoteEndpointResponse\022F\n\022GetLoggingEndpo"
+  "int\022\017.dmi.HardwareID\032\037.dmi.GetLoggingEnd"
+  "pointResponse\022R\n\021SetMsgBusEndpoint\022\035.dmi"
+  ".SetMsgBusEndpointRequest\032\036.dmi.SetRemot"
+  "eEndpointResponse\022K\n\021GetMsgBusEndpoint\022\026"
+  ".google.protobuf.Empty\032\036.dmi.GetMsgBusEn"
+  "dpointResponse\022P\n\023GetLoggableEntities\022\037."
+  "dmi.GetLoggableEntitiesRequest\032\030.dmi.Get"
+  "LogLevelResponse\022@\n\013SetLogLevel\022\027.dmi.Se"
+  "tLogLevelRequest\032\030.dmi.SetLogLevelRespon"
+  "se\022@\n\013GetLogLevel\022\027.dmi.GetLogLevelReque"
+  "st\032\030.dmi.GetLogLevelResponseB;Z9github.c"
+  "om/opencord/device-management-interface/"
+  "v3/go/dmib\006proto3"
+  ;
+::google::protobuf::internal::DescriptorTable descriptor_table_dmi_2fhw_5fmanagement_5fservice_2eproto = {
+  false, InitDefaults_dmi_2fhw_5fmanagement_5fservice_2eproto, 
+  descriptor_table_protodef_dmi_2fhw_5fmanagement_5fservice_2eproto,
+  "dmi/hw_management_service.proto", &assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto, 5177,
+};
+
+void AddDescriptors_dmi_2fhw_5fmanagement_5fservice_2eproto() {
+  static constexpr ::google::protobuf::internal::InitFunc deps[3] =
+  {
+    ::AddDescriptors_dmi_2fcommons_2eproto,
+    ::AddDescriptors_dmi_2fhw_2eproto,
+    ::AddDescriptors_google_2fprotobuf_2fempty_2eproto,
+  };
+ ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fhw_5fmanagement_5fservice_2eproto, deps, 3);
+}
+
+// Force running AddDescriptors() at dynamic initialization time.
+static bool dynamic_init_dummy_dmi_2fhw_5fmanagement_5fservice_2eproto = []() { AddDescriptors_dmi_2fhw_5fmanagement_5fservice_2eproto(); return true; }();
+namespace dmi {
+const ::google::protobuf::EnumDescriptor* PhysicalInventoryResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto[0];
+}
+bool PhysicalInventoryResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const PhysicalInventoryResponse_Reason PhysicalInventoryResponse::UNDEFINED_REASON;
+const PhysicalInventoryResponse_Reason PhysicalInventoryResponse::UNKNOWN_DEVICE;
+const PhysicalInventoryResponse_Reason PhysicalInventoryResponse::INTERNAL_ERROR;
+const PhysicalInventoryResponse_Reason PhysicalInventoryResponse::DEVICE_UNREACHABLE;
+const PhysicalInventoryResponse_Reason PhysicalInventoryResponse::Reason_MIN;
+const PhysicalInventoryResponse_Reason PhysicalInventoryResponse::Reason_MAX;
+const int PhysicalInventoryResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* HWComponentInfoGetResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto[1];
+}
+bool HWComponentInfoGetResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const HWComponentInfoGetResponse_Reason HWComponentInfoGetResponse::UNDEFINED_REASON;
+const HWComponentInfoGetResponse_Reason HWComponentInfoGetResponse::UNKNOWN_DEVICE;
+const HWComponentInfoGetResponse_Reason HWComponentInfoGetResponse::UNKNOWN_COMPONENT;
+const HWComponentInfoGetResponse_Reason HWComponentInfoGetResponse::INTERNAL_ERROR;
+const HWComponentInfoGetResponse_Reason HWComponentInfoGetResponse::DEVICE_UNREACHABLE;
+const HWComponentInfoGetResponse_Reason HWComponentInfoGetResponse::Reason_MIN;
+const HWComponentInfoGetResponse_Reason HWComponentInfoGetResponse::Reason_MAX;
+const int HWComponentInfoGetResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* HWComponentInfoSetResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto[2];
+}
+bool HWComponentInfoSetResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const HWComponentInfoSetResponse_Reason HWComponentInfoSetResponse::UNDEFINED_REASON;
+const HWComponentInfoSetResponse_Reason HWComponentInfoSetResponse::UNKNOWN_DEVICE;
+const HWComponentInfoSetResponse_Reason HWComponentInfoSetResponse::UNKNOWN_COMPONENT;
+const HWComponentInfoSetResponse_Reason HWComponentInfoSetResponse::INVALID_PARAMS;
+const HWComponentInfoSetResponse_Reason HWComponentInfoSetResponse::INTERNAL_ERROR;
+const HWComponentInfoSetResponse_Reason HWComponentInfoSetResponse::DEVICE_UNREACHABLE;
+const HWComponentInfoSetResponse_Reason HWComponentInfoSetResponse::Reason_MIN;
+const HWComponentInfoSetResponse_Reason HWComponentInfoSetResponse::Reason_MAX;
+const int HWComponentInfoSetResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* StartManagingDeviceResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto[3];
+}
+bool StartManagingDeviceResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const StartManagingDeviceResponse_Reason StartManagingDeviceResponse::UNDEFINED_REASON;
+const StartManagingDeviceResponse_Reason StartManagingDeviceResponse::DEVICE_ALREADY_MANAGED;
+const StartManagingDeviceResponse_Reason StartManagingDeviceResponse::OPERATION_ALREADY_IN_PROGRESS;
+const StartManagingDeviceResponse_Reason StartManagingDeviceResponse::INVALID_PARAMS;
+const StartManagingDeviceResponse_Reason StartManagingDeviceResponse::INTERNAL_ERROR;
+const StartManagingDeviceResponse_Reason StartManagingDeviceResponse::Reason_MIN;
+const StartManagingDeviceResponse_Reason StartManagingDeviceResponse::Reason_MAX;
+const int StartManagingDeviceResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* StopManagingDeviceResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto[4];
+}
+bool StopManagingDeviceResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const StopManagingDeviceResponse_Reason StopManagingDeviceResponse::UNDEFINED_REASON;
+const StopManagingDeviceResponse_Reason StopManagingDeviceResponse::UNKNOWN_DEVICE;
+const StopManagingDeviceResponse_Reason StopManagingDeviceResponse::Reason_MIN;
+const StopManagingDeviceResponse_Reason StopManagingDeviceResponse::Reason_MAX;
+const int StopManagingDeviceResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* ManagedDevicesResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto[5];
+}
+bool ManagedDevicesResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const ManagedDevicesResponse_Reason ManagedDevicesResponse::UNDEFINED_REASON;
+const ManagedDevicesResponse_Reason ManagedDevicesResponse::INTERNAL_ERROR;
+const ManagedDevicesResponse_Reason ManagedDevicesResponse::Reason_MIN;
+const ManagedDevicesResponse_Reason ManagedDevicesResponse::Reason_MAX;
+const int ManagedDevicesResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* SetRemoteEndpointResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto[6];
+}
+bool SetRemoteEndpointResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const SetRemoteEndpointResponse_Reason SetRemoteEndpointResponse::UNDEFINED_REASON;
+const SetRemoteEndpointResponse_Reason SetRemoteEndpointResponse::UNKNOWN_DEVICE;
+const SetRemoteEndpointResponse_Reason SetRemoteEndpointResponse::INTERNAL_ERROR;
+const SetRemoteEndpointResponse_Reason SetRemoteEndpointResponse::LOGGING_ENDPOINT_ERROR;
+const SetRemoteEndpointResponse_Reason SetRemoteEndpointResponse::LOGGING_ENDPOINT_PROTOCOL_ERROR;
+const SetRemoteEndpointResponse_Reason SetRemoteEndpointResponse::MSGBUS_ENDPOINT_ERROR;
+const SetRemoteEndpointResponse_Reason SetRemoteEndpointResponse::DEVICE_UNREACHABLE;
+const SetRemoteEndpointResponse_Reason SetRemoteEndpointResponse::Reason_MIN;
+const SetRemoteEndpointResponse_Reason SetRemoteEndpointResponse::Reason_MAX;
+const int SetRemoteEndpointResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* GetLoggingEndpointResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto[7];
+}
+bool GetLoggingEndpointResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const GetLoggingEndpointResponse_Reason GetLoggingEndpointResponse::UNDEFINED_REASON;
+const GetLoggingEndpointResponse_Reason GetLoggingEndpointResponse::UNKNOWN_DEVICE;
+const GetLoggingEndpointResponse_Reason GetLoggingEndpointResponse::INTERNAL_ERROR;
+const GetLoggingEndpointResponse_Reason GetLoggingEndpointResponse::DEVICE_UNREACHABLE;
+const GetLoggingEndpointResponse_Reason GetLoggingEndpointResponse::Reason_MIN;
+const GetLoggingEndpointResponse_Reason GetLoggingEndpointResponse::Reason_MAX;
+const int GetLoggingEndpointResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* GetMsgBusEndpointResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto[8];
+}
+bool GetMsgBusEndpointResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const GetMsgBusEndpointResponse_Reason GetMsgBusEndpointResponse::UNDEFINED_REASON;
+const GetMsgBusEndpointResponse_Reason GetMsgBusEndpointResponse::INTERNAL_ERROR;
+const GetMsgBusEndpointResponse_Reason GetMsgBusEndpointResponse::DEVICE_UNREACHABLE;
+const GetMsgBusEndpointResponse_Reason GetMsgBusEndpointResponse::Reason_MIN;
+const GetMsgBusEndpointResponse_Reason GetMsgBusEndpointResponse::Reason_MAX;
+const int GetMsgBusEndpointResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* SetLogLevelResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto[9];
+}
+bool SetLogLevelResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const SetLogLevelResponse_Reason SetLogLevelResponse::UNDEFINED_REASON;
+const SetLogLevelResponse_Reason SetLogLevelResponse::UNKNOWN_DEVICE;
+const SetLogLevelResponse_Reason SetLogLevelResponse::INTERNAL_ERROR;
+const SetLogLevelResponse_Reason SetLogLevelResponse::UNKNOWN_LOG_ENTITY;
+const SetLogLevelResponse_Reason SetLogLevelResponse::DEVICE_UNREACHABLE;
+const SetLogLevelResponse_Reason SetLogLevelResponse::Reason_MIN;
+const SetLogLevelResponse_Reason SetLogLevelResponse::Reason_MAX;
+const int SetLogLevelResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* GetLogLevelResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmanagement_5fservice_2eproto[10];
+}
+bool GetLogLevelResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const GetLogLevelResponse_Reason GetLogLevelResponse::UNDEFINED_REASON;
+const GetLogLevelResponse_Reason GetLogLevelResponse::UNKNOWN_DEVICE;
+const GetLogLevelResponse_Reason GetLogLevelResponse::INTERNAL_ERROR;
+const GetLogLevelResponse_Reason GetLogLevelResponse::UNKNOWN_LOG_ENTITY;
+const GetLogLevelResponse_Reason GetLogLevelResponse::DEVICE_UNREACHABLE;
+const GetLogLevelResponse_Reason GetLogLevelResponse::Reason_MIN;
+const GetLogLevelResponse_Reason GetLogLevelResponse::Reason_MAX;
+const int GetLogLevelResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+// ===================================================================
+
+void PhysicalInventoryRequest::InitAsDefaultInstance() {
+  ::dmi::_PhysicalInventoryRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class PhysicalInventoryRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const PhysicalInventoryRequest* msg);
+};
+
+const ::dmi::Uuid&
+PhysicalInventoryRequest::HasBitSetters::device_uuid(const PhysicalInventoryRequest* msg) {
+  return *msg->device_uuid_;
+}
+void PhysicalInventoryRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int PhysicalInventoryRequest::kDeviceUuidFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+PhysicalInventoryRequest::PhysicalInventoryRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.PhysicalInventoryRequest)
+}
+PhysicalInventoryRequest::PhysicalInventoryRequest(const PhysicalInventoryRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.PhysicalInventoryRequest)
+}
+
+void PhysicalInventoryRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_PhysicalInventoryRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  device_uuid_ = nullptr;
+}
+
+PhysicalInventoryRequest::~PhysicalInventoryRequest() {
+  // @@protoc_insertion_point(destructor:dmi.PhysicalInventoryRequest)
+  SharedDtor();
+}
+
+void PhysicalInventoryRequest::SharedDtor() {
+  if (this != internal_default_instance()) delete device_uuid_;
+}
+
+void PhysicalInventoryRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const PhysicalInventoryRequest& PhysicalInventoryRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_PhysicalInventoryRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void PhysicalInventoryRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.PhysicalInventoryRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* PhysicalInventoryRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<PhysicalInventoryRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool PhysicalInventoryRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.PhysicalInventoryRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.PhysicalInventoryRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.PhysicalInventoryRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void PhysicalInventoryRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.PhysicalInventoryRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.PhysicalInventoryRequest)
+}
+
+::google::protobuf::uint8* PhysicalInventoryRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.PhysicalInventoryRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.PhysicalInventoryRequest)
+  return target;
+}
+
+size_t PhysicalInventoryRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.PhysicalInventoryRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void PhysicalInventoryRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.PhysicalInventoryRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const PhysicalInventoryRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<PhysicalInventoryRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.PhysicalInventoryRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.PhysicalInventoryRequest)
+    MergeFrom(*source);
+  }
+}
+
+void PhysicalInventoryRequest::MergeFrom(const PhysicalInventoryRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.PhysicalInventoryRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+}
+
+void PhysicalInventoryRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.PhysicalInventoryRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void PhysicalInventoryRequest::CopyFrom(const PhysicalInventoryRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.PhysicalInventoryRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool PhysicalInventoryRequest::IsInitialized() const {
+  return true;
+}
+
+void PhysicalInventoryRequest::Swap(PhysicalInventoryRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void PhysicalInventoryRequest::InternalSwap(PhysicalInventoryRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(device_uuid_, other->device_uuid_);
+}
+
+::google::protobuf::Metadata PhysicalInventoryRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void PhysicalInventoryResponse::InitAsDefaultInstance() {
+  ::dmi::_PhysicalInventoryResponse_default_instance_._instance.get_mutable()->inventory_ = const_cast< ::dmi::Hardware*>(
+      ::dmi::Hardware::internal_default_instance());
+}
+class PhysicalInventoryResponse::HasBitSetters {
+ public:
+  static const ::dmi::Hardware& inventory(const PhysicalInventoryResponse* msg);
+};
+
+const ::dmi::Hardware&
+PhysicalInventoryResponse::HasBitSetters::inventory(const PhysicalInventoryResponse* msg) {
+  return *msg->inventory_;
+}
+void PhysicalInventoryResponse::clear_inventory() {
+  if (GetArenaNoVirtual() == nullptr && inventory_ != nullptr) {
+    delete inventory_;
+  }
+  inventory_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int PhysicalInventoryResponse::kStatusFieldNumber;
+const int PhysicalInventoryResponse::kReasonFieldNumber;
+const int PhysicalInventoryResponse::kInventoryFieldNumber;
+const int PhysicalInventoryResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+PhysicalInventoryResponse::PhysicalInventoryResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.PhysicalInventoryResponse)
+}
+PhysicalInventoryResponse::PhysicalInventoryResponse(const PhysicalInventoryResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_inventory()) {
+    inventory_ = new ::dmi::Hardware(*from.inventory_);
+  } else {
+    inventory_ = nullptr;
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.PhysicalInventoryResponse)
+}
+
+void PhysicalInventoryResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_PhysicalInventoryResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&inventory_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&inventory_)) + sizeof(reason_));
+}
+
+PhysicalInventoryResponse::~PhysicalInventoryResponse() {
+  // @@protoc_insertion_point(destructor:dmi.PhysicalInventoryResponse)
+  SharedDtor();
+}
+
+void PhysicalInventoryResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete inventory_;
+}
+
+void PhysicalInventoryResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const PhysicalInventoryResponse& PhysicalInventoryResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_PhysicalInventoryResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void PhysicalInventoryResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.PhysicalInventoryResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && inventory_ != nullptr) {
+    delete inventory_;
+  }
+  inventory_ = nullptr;
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* PhysicalInventoryResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<PhysicalInventoryResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.PhysicalInventoryResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::PhysicalInventoryResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.Hardware inventory = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Hardware::_InternalParse;
+        object = msg->mutable_inventory();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.PhysicalInventoryResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool PhysicalInventoryResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.PhysicalInventoryResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.PhysicalInventoryResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::PhysicalInventoryResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Hardware inventory = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_inventory()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.PhysicalInventoryResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.PhysicalInventoryResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.PhysicalInventoryResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void PhysicalInventoryResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.PhysicalInventoryResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.PhysicalInventoryResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // .dmi.Hardware inventory = 3;
+  if (this->has_inventory()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::inventory(this), output);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.PhysicalInventoryResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.PhysicalInventoryResponse)
+}
+
+::google::protobuf::uint8* PhysicalInventoryResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.PhysicalInventoryResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.PhysicalInventoryResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // .dmi.Hardware inventory = 3;
+  if (this->has_inventory()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::inventory(this), target);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.PhysicalInventoryResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.PhysicalInventoryResponse)
+  return target;
+}
+
+size_t PhysicalInventoryResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.PhysicalInventoryResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Hardware inventory = 3;
+  if (this->has_inventory()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *inventory_);
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.PhysicalInventoryResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void PhysicalInventoryResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.PhysicalInventoryResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const PhysicalInventoryResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<PhysicalInventoryResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.PhysicalInventoryResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.PhysicalInventoryResponse)
+    MergeFrom(*source);
+  }
+}
+
+void PhysicalInventoryResponse::MergeFrom(const PhysicalInventoryResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.PhysicalInventoryResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_inventory()) {
+    mutable_inventory()->::dmi::Hardware::MergeFrom(from.inventory());
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void PhysicalInventoryResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.PhysicalInventoryResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void PhysicalInventoryResponse::CopyFrom(const PhysicalInventoryResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.PhysicalInventoryResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool PhysicalInventoryResponse::IsInitialized() const {
+  return true;
+}
+
+void PhysicalInventoryResponse::Swap(PhysicalInventoryResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void PhysicalInventoryResponse::InternalSwap(PhysicalInventoryResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(inventory_, other->inventory_);
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata PhysicalInventoryResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void HWComponentInfoGetRequest::InitAsDefaultInstance() {
+  ::dmi::_HWComponentInfoGetRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+  ::dmi::_HWComponentInfoGetRequest_default_instance_._instance.get_mutable()->component_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class HWComponentInfoGetRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const HWComponentInfoGetRequest* msg);
+  static const ::dmi::Uuid& component_uuid(const HWComponentInfoGetRequest* msg);
+};
+
+const ::dmi::Uuid&
+HWComponentInfoGetRequest::HasBitSetters::device_uuid(const HWComponentInfoGetRequest* msg) {
+  return *msg->device_uuid_;
+}
+const ::dmi::Uuid&
+HWComponentInfoGetRequest::HasBitSetters::component_uuid(const HWComponentInfoGetRequest* msg) {
+  return *msg->component_uuid_;
+}
+void HWComponentInfoGetRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+void HWComponentInfoGetRequest::clear_component_uuid() {
+  if (GetArenaNoVirtual() == nullptr && component_uuid_ != nullptr) {
+    delete component_uuid_;
+  }
+  component_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int HWComponentInfoGetRequest::kDeviceUuidFieldNumber;
+const int HWComponentInfoGetRequest::kComponentUuidFieldNumber;
+const int HWComponentInfoGetRequest::kComponentNameFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+HWComponentInfoGetRequest::HWComponentInfoGetRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.HWComponentInfoGetRequest)
+}
+HWComponentInfoGetRequest::HWComponentInfoGetRequest(const HWComponentInfoGetRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  component_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.component_name().size() > 0) {
+    component_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.component_name_);
+  }
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  if (from.has_component_uuid()) {
+    component_uuid_ = new ::dmi::Uuid(*from.component_uuid_);
+  } else {
+    component_uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.HWComponentInfoGetRequest)
+}
+
+void HWComponentInfoGetRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_HWComponentInfoGetRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  component_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&device_uuid_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&component_uuid_) -
+      reinterpret_cast<char*>(&device_uuid_)) + sizeof(component_uuid_));
+}
+
+HWComponentInfoGetRequest::~HWComponentInfoGetRequest() {
+  // @@protoc_insertion_point(destructor:dmi.HWComponentInfoGetRequest)
+  SharedDtor();
+}
+
+void HWComponentInfoGetRequest::SharedDtor() {
+  component_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete device_uuid_;
+  if (this != internal_default_instance()) delete component_uuid_;
+}
+
+void HWComponentInfoGetRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const HWComponentInfoGetRequest& HWComponentInfoGetRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_HWComponentInfoGetRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void HWComponentInfoGetRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.HWComponentInfoGetRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  component_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && component_uuid_ != nullptr) {
+    delete component_uuid_;
+  }
+  component_uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* HWComponentInfoGetRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<HWComponentInfoGetRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.Uuid component_uuid = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_component_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string component_name = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.HWComponentInfoGetRequest.component_name");
+        object = msg->mutable_component_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool HWComponentInfoGetRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.HWComponentInfoGetRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Uuid component_uuid = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_component_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string component_name = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_component_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->component_name().data(), static_cast<int>(this->component_name().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.HWComponentInfoGetRequest.component_name"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.HWComponentInfoGetRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.HWComponentInfoGetRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void HWComponentInfoGetRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.HWComponentInfoGetRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::component_uuid(this), output);
+  }
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->component_name().data(), static_cast<int>(this->component_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.HWComponentInfoGetRequest.component_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->component_name(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.HWComponentInfoGetRequest)
+}
+
+::google::protobuf::uint8* HWComponentInfoGetRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.HWComponentInfoGetRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::component_uuid(this), target);
+  }
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->component_name().data(), static_cast<int>(this->component_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.HWComponentInfoGetRequest.component_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->component_name(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.HWComponentInfoGetRequest)
+  return target;
+}
+
+size_t HWComponentInfoGetRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.HWComponentInfoGetRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->component_name());
+  }
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *component_uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void HWComponentInfoGetRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.HWComponentInfoGetRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const HWComponentInfoGetRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<HWComponentInfoGetRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.HWComponentInfoGetRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.HWComponentInfoGetRequest)
+    MergeFrom(*source);
+  }
+}
+
+void HWComponentInfoGetRequest::MergeFrom(const HWComponentInfoGetRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.HWComponentInfoGetRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.component_name().size() > 0) {
+
+    component_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.component_name_);
+  }
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+  if (from.has_component_uuid()) {
+    mutable_component_uuid()->::dmi::Uuid::MergeFrom(from.component_uuid());
+  }
+}
+
+void HWComponentInfoGetRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.HWComponentInfoGetRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void HWComponentInfoGetRequest::CopyFrom(const HWComponentInfoGetRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.HWComponentInfoGetRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool HWComponentInfoGetRequest::IsInitialized() const {
+  return true;
+}
+
+void HWComponentInfoGetRequest::Swap(HWComponentInfoGetRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void HWComponentInfoGetRequest::InternalSwap(HWComponentInfoGetRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  component_name_.Swap(&other->component_name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(device_uuid_, other->device_uuid_);
+  swap(component_uuid_, other->component_uuid_);
+}
+
+::google::protobuf::Metadata HWComponentInfoGetRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void HWComponentInfoGetResponse::InitAsDefaultInstance() {
+  ::dmi::_HWComponentInfoGetResponse_default_instance_._instance.get_mutable()->component_ = const_cast< ::dmi::Component*>(
+      ::dmi::Component::internal_default_instance());
+}
+class HWComponentInfoGetResponse::HasBitSetters {
+ public:
+  static const ::dmi::Component& component(const HWComponentInfoGetResponse* msg);
+};
+
+const ::dmi::Component&
+HWComponentInfoGetResponse::HasBitSetters::component(const HWComponentInfoGetResponse* msg) {
+  return *msg->component_;
+}
+void HWComponentInfoGetResponse::clear_component() {
+  if (GetArenaNoVirtual() == nullptr && component_ != nullptr) {
+    delete component_;
+  }
+  component_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int HWComponentInfoGetResponse::kStatusFieldNumber;
+const int HWComponentInfoGetResponse::kReasonFieldNumber;
+const int HWComponentInfoGetResponse::kComponentFieldNumber;
+const int HWComponentInfoGetResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+HWComponentInfoGetResponse::HWComponentInfoGetResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.HWComponentInfoGetResponse)
+}
+HWComponentInfoGetResponse::HWComponentInfoGetResponse(const HWComponentInfoGetResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_component()) {
+    component_ = new ::dmi::Component(*from.component_);
+  } else {
+    component_ = nullptr;
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.HWComponentInfoGetResponse)
+}
+
+void HWComponentInfoGetResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_HWComponentInfoGetResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&component_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&component_)) + sizeof(reason_));
+}
+
+HWComponentInfoGetResponse::~HWComponentInfoGetResponse() {
+  // @@protoc_insertion_point(destructor:dmi.HWComponentInfoGetResponse)
+  SharedDtor();
+}
+
+void HWComponentInfoGetResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete component_;
+}
+
+void HWComponentInfoGetResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const HWComponentInfoGetResponse& HWComponentInfoGetResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_HWComponentInfoGetResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void HWComponentInfoGetResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.HWComponentInfoGetResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && component_ != nullptr) {
+    delete component_;
+  }
+  component_ = nullptr;
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* HWComponentInfoGetResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<HWComponentInfoGetResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.HWComponentInfoGetResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::HWComponentInfoGetResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.Component component = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Component::_InternalParse;
+        object = msg->mutable_component();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.HWComponentInfoGetResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool HWComponentInfoGetResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.HWComponentInfoGetResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.HWComponentInfoGetResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::HWComponentInfoGetResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Component component = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_component()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.HWComponentInfoGetResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.HWComponentInfoGetResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.HWComponentInfoGetResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void HWComponentInfoGetResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.HWComponentInfoGetResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.HWComponentInfoGetResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // .dmi.Component component = 3;
+  if (this->has_component()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::component(this), output);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.HWComponentInfoGetResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.HWComponentInfoGetResponse)
+}
+
+::google::protobuf::uint8* HWComponentInfoGetResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.HWComponentInfoGetResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.HWComponentInfoGetResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // .dmi.Component component = 3;
+  if (this->has_component()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::component(this), target);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.HWComponentInfoGetResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.HWComponentInfoGetResponse)
+  return target;
+}
+
+size_t HWComponentInfoGetResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.HWComponentInfoGetResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Component component = 3;
+  if (this->has_component()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *component_);
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.HWComponentInfoGetResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void HWComponentInfoGetResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.HWComponentInfoGetResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const HWComponentInfoGetResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<HWComponentInfoGetResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.HWComponentInfoGetResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.HWComponentInfoGetResponse)
+    MergeFrom(*source);
+  }
+}
+
+void HWComponentInfoGetResponse::MergeFrom(const HWComponentInfoGetResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.HWComponentInfoGetResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_component()) {
+    mutable_component()->::dmi::Component::MergeFrom(from.component());
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void HWComponentInfoGetResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.HWComponentInfoGetResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void HWComponentInfoGetResponse::CopyFrom(const HWComponentInfoGetResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.HWComponentInfoGetResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool HWComponentInfoGetResponse::IsInitialized() const {
+  return true;
+}
+
+void HWComponentInfoGetResponse::Swap(HWComponentInfoGetResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void HWComponentInfoGetResponse::InternalSwap(HWComponentInfoGetResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(component_, other->component_);
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata HWComponentInfoGetResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void HWComponentInfoSetRequest::InitAsDefaultInstance() {
+  ::dmi::_HWComponentInfoSetRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+  ::dmi::_HWComponentInfoSetRequest_default_instance_._instance.get_mutable()->component_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+  ::dmi::_HWComponentInfoSetRequest_default_instance_._instance.get_mutable()->changes_ = const_cast< ::dmi::ModifiableComponent*>(
+      ::dmi::ModifiableComponent::internal_default_instance());
+}
+class HWComponentInfoSetRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const HWComponentInfoSetRequest* msg);
+  static const ::dmi::Uuid& component_uuid(const HWComponentInfoSetRequest* msg);
+  static const ::dmi::ModifiableComponent& changes(const HWComponentInfoSetRequest* msg);
+};
+
+const ::dmi::Uuid&
+HWComponentInfoSetRequest::HasBitSetters::device_uuid(const HWComponentInfoSetRequest* msg) {
+  return *msg->device_uuid_;
+}
+const ::dmi::Uuid&
+HWComponentInfoSetRequest::HasBitSetters::component_uuid(const HWComponentInfoSetRequest* msg) {
+  return *msg->component_uuid_;
+}
+const ::dmi::ModifiableComponent&
+HWComponentInfoSetRequest::HasBitSetters::changes(const HWComponentInfoSetRequest* msg) {
+  return *msg->changes_;
+}
+void HWComponentInfoSetRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+void HWComponentInfoSetRequest::clear_component_uuid() {
+  if (GetArenaNoVirtual() == nullptr && component_uuid_ != nullptr) {
+    delete component_uuid_;
+  }
+  component_uuid_ = nullptr;
+}
+void HWComponentInfoSetRequest::clear_changes() {
+  if (GetArenaNoVirtual() == nullptr && changes_ != nullptr) {
+    delete changes_;
+  }
+  changes_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int HWComponentInfoSetRequest::kDeviceUuidFieldNumber;
+const int HWComponentInfoSetRequest::kComponentUuidFieldNumber;
+const int HWComponentInfoSetRequest::kComponentNameFieldNumber;
+const int HWComponentInfoSetRequest::kChangesFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+HWComponentInfoSetRequest::HWComponentInfoSetRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.HWComponentInfoSetRequest)
+}
+HWComponentInfoSetRequest::HWComponentInfoSetRequest(const HWComponentInfoSetRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  component_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.component_name().size() > 0) {
+    component_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.component_name_);
+  }
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  if (from.has_component_uuid()) {
+    component_uuid_ = new ::dmi::Uuid(*from.component_uuid_);
+  } else {
+    component_uuid_ = nullptr;
+  }
+  if (from.has_changes()) {
+    changes_ = new ::dmi::ModifiableComponent(*from.changes_);
+  } else {
+    changes_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.HWComponentInfoSetRequest)
+}
+
+void HWComponentInfoSetRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_HWComponentInfoSetRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  component_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&device_uuid_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&changes_) -
+      reinterpret_cast<char*>(&device_uuid_)) + sizeof(changes_));
+}
+
+HWComponentInfoSetRequest::~HWComponentInfoSetRequest() {
+  // @@protoc_insertion_point(destructor:dmi.HWComponentInfoSetRequest)
+  SharedDtor();
+}
+
+void HWComponentInfoSetRequest::SharedDtor() {
+  component_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete device_uuid_;
+  if (this != internal_default_instance()) delete component_uuid_;
+  if (this != internal_default_instance()) delete changes_;
+}
+
+void HWComponentInfoSetRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const HWComponentInfoSetRequest& HWComponentInfoSetRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_HWComponentInfoSetRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void HWComponentInfoSetRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.HWComponentInfoSetRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  component_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && component_uuid_ != nullptr) {
+    delete component_uuid_;
+  }
+  component_uuid_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && changes_ != nullptr) {
+    delete changes_;
+  }
+  changes_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* HWComponentInfoSetRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<HWComponentInfoSetRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.Uuid component_uuid = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_component_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string component_name = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.HWComponentInfoSetRequest.component_name");
+        object = msg->mutable_component_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // .dmi.ModifiableComponent changes = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::ModifiableComponent::_InternalParse;
+        object = msg->mutable_changes();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool HWComponentInfoSetRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.HWComponentInfoSetRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Uuid component_uuid = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_component_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string component_name = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_component_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->component_name().data(), static_cast<int>(this->component_name().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.HWComponentInfoSetRequest.component_name"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ModifiableComponent changes = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_changes()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.HWComponentInfoSetRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.HWComponentInfoSetRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void HWComponentInfoSetRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.HWComponentInfoSetRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::component_uuid(this), output);
+  }
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->component_name().data(), static_cast<int>(this->component_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.HWComponentInfoSetRequest.component_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->component_name(), output);
+  }
+
+  // .dmi.ModifiableComponent changes = 4;
+  if (this->has_changes()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      4, HasBitSetters::changes(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.HWComponentInfoSetRequest)
+}
+
+::google::protobuf::uint8* HWComponentInfoSetRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.HWComponentInfoSetRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::component_uuid(this), target);
+  }
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->component_name().data(), static_cast<int>(this->component_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.HWComponentInfoSetRequest.component_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->component_name(), target);
+  }
+
+  // .dmi.ModifiableComponent changes = 4;
+  if (this->has_changes()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        4, HasBitSetters::changes(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.HWComponentInfoSetRequest)
+  return target;
+}
+
+size_t HWComponentInfoSetRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.HWComponentInfoSetRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->component_name());
+  }
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *component_uuid_);
+  }
+
+  // .dmi.ModifiableComponent changes = 4;
+  if (this->has_changes()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *changes_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void HWComponentInfoSetRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.HWComponentInfoSetRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const HWComponentInfoSetRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<HWComponentInfoSetRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.HWComponentInfoSetRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.HWComponentInfoSetRequest)
+    MergeFrom(*source);
+  }
+}
+
+void HWComponentInfoSetRequest::MergeFrom(const HWComponentInfoSetRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.HWComponentInfoSetRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.component_name().size() > 0) {
+
+    component_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.component_name_);
+  }
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+  if (from.has_component_uuid()) {
+    mutable_component_uuid()->::dmi::Uuid::MergeFrom(from.component_uuid());
+  }
+  if (from.has_changes()) {
+    mutable_changes()->::dmi::ModifiableComponent::MergeFrom(from.changes());
+  }
+}
+
+void HWComponentInfoSetRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.HWComponentInfoSetRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void HWComponentInfoSetRequest::CopyFrom(const HWComponentInfoSetRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.HWComponentInfoSetRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool HWComponentInfoSetRequest::IsInitialized() const {
+  return true;
+}
+
+void HWComponentInfoSetRequest::Swap(HWComponentInfoSetRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void HWComponentInfoSetRequest::InternalSwap(HWComponentInfoSetRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  component_name_.Swap(&other->component_name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(device_uuid_, other->device_uuid_);
+  swap(component_uuid_, other->component_uuid_);
+  swap(changes_, other->changes_);
+}
+
+::google::protobuf::Metadata HWComponentInfoSetRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void HWComponentInfoSetResponse::InitAsDefaultInstance() {
+}
+class HWComponentInfoSetResponse::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int HWComponentInfoSetResponse::kStatusFieldNumber;
+const int HWComponentInfoSetResponse::kReasonFieldNumber;
+const int HWComponentInfoSetResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+HWComponentInfoSetResponse::HWComponentInfoSetResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.HWComponentInfoSetResponse)
+}
+HWComponentInfoSetResponse::HWComponentInfoSetResponse(const HWComponentInfoSetResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.HWComponentInfoSetResponse)
+}
+
+void HWComponentInfoSetResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_HWComponentInfoSetResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+}
+
+HWComponentInfoSetResponse::~HWComponentInfoSetResponse() {
+  // @@protoc_insertion_point(destructor:dmi.HWComponentInfoSetResponse)
+  SharedDtor();
+}
+
+void HWComponentInfoSetResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void HWComponentInfoSetResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const HWComponentInfoSetResponse& HWComponentInfoSetResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_HWComponentInfoSetResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void HWComponentInfoSetResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.HWComponentInfoSetResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* HWComponentInfoSetResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<HWComponentInfoSetResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.HWComponentInfoSetResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::HWComponentInfoSetResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.HWComponentInfoSetResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool HWComponentInfoSetResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.HWComponentInfoSetResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.HWComponentInfoSetResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::HWComponentInfoSetResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.HWComponentInfoSetResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.HWComponentInfoSetResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.HWComponentInfoSetResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void HWComponentInfoSetResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.HWComponentInfoSetResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.HWComponentInfoSetResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.HWComponentInfoSetResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.HWComponentInfoSetResponse)
+}
+
+::google::protobuf::uint8* HWComponentInfoSetResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.HWComponentInfoSetResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.HWComponentInfoSetResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.HWComponentInfoSetResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.HWComponentInfoSetResponse)
+  return target;
+}
+
+size_t HWComponentInfoSetResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.HWComponentInfoSetResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.HWComponentInfoSetResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void HWComponentInfoSetResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.HWComponentInfoSetResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const HWComponentInfoSetResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<HWComponentInfoSetResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.HWComponentInfoSetResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.HWComponentInfoSetResponse)
+    MergeFrom(*source);
+  }
+}
+
+void HWComponentInfoSetResponse::MergeFrom(const HWComponentInfoSetResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.HWComponentInfoSetResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void HWComponentInfoSetResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.HWComponentInfoSetResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void HWComponentInfoSetResponse::CopyFrom(const HWComponentInfoSetResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.HWComponentInfoSetResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool HWComponentInfoSetResponse::IsInitialized() const {
+  return true;
+}
+
+void HWComponentInfoSetResponse::Swap(HWComponentInfoSetResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void HWComponentInfoSetResponse::InternalSwap(HWComponentInfoSetResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata HWComponentInfoSetResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void StartManagingDeviceResponse::InitAsDefaultInstance() {
+  ::dmi::_StartManagingDeviceResponse_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class StartManagingDeviceResponse::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const StartManagingDeviceResponse* msg);
+};
+
+const ::dmi::Uuid&
+StartManagingDeviceResponse::HasBitSetters::device_uuid(const StartManagingDeviceResponse* msg) {
+  return *msg->device_uuid_;
+}
+void StartManagingDeviceResponse::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int StartManagingDeviceResponse::kStatusFieldNumber;
+const int StartManagingDeviceResponse::kReasonFieldNumber;
+const int StartManagingDeviceResponse::kDeviceUuidFieldNumber;
+const int StartManagingDeviceResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+StartManagingDeviceResponse::StartManagingDeviceResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.StartManagingDeviceResponse)
+}
+StartManagingDeviceResponse::StartManagingDeviceResponse(const StartManagingDeviceResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.StartManagingDeviceResponse)
+}
+
+void StartManagingDeviceResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_StartManagingDeviceResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&device_uuid_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&device_uuid_)) + sizeof(reason_));
+}
+
+StartManagingDeviceResponse::~StartManagingDeviceResponse() {
+  // @@protoc_insertion_point(destructor:dmi.StartManagingDeviceResponse)
+  SharedDtor();
+}
+
+void StartManagingDeviceResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete device_uuid_;
+}
+
+void StartManagingDeviceResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const StartManagingDeviceResponse& StartManagingDeviceResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_StartManagingDeviceResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void StartManagingDeviceResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.StartManagingDeviceResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* StartManagingDeviceResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<StartManagingDeviceResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.StartManagingDeviceResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::StartManagingDeviceResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.Uuid device_uuid = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.StartManagingDeviceResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool StartManagingDeviceResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.StartManagingDeviceResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.StartManagingDeviceResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::StartManagingDeviceResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Uuid device_uuid = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.StartManagingDeviceResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.StartManagingDeviceResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.StartManagingDeviceResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void StartManagingDeviceResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.StartManagingDeviceResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.StartManagingDeviceResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // .dmi.Uuid device_uuid = 3;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::device_uuid(this), output);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.StartManagingDeviceResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.StartManagingDeviceResponse)
+}
+
+::google::protobuf::uint8* StartManagingDeviceResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.StartManagingDeviceResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.StartManagingDeviceResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // .dmi.Uuid device_uuid = 3;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::device_uuid(this), target);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.StartManagingDeviceResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.StartManagingDeviceResponse)
+  return target;
+}
+
+size_t StartManagingDeviceResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.StartManagingDeviceResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Uuid device_uuid = 3;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.StartManagingDeviceResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void StartManagingDeviceResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.StartManagingDeviceResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const StartManagingDeviceResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<StartManagingDeviceResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.StartManagingDeviceResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.StartManagingDeviceResponse)
+    MergeFrom(*source);
+  }
+}
+
+void StartManagingDeviceResponse::MergeFrom(const StartManagingDeviceResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.StartManagingDeviceResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void StartManagingDeviceResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.StartManagingDeviceResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void StartManagingDeviceResponse::CopyFrom(const StartManagingDeviceResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.StartManagingDeviceResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool StartManagingDeviceResponse::IsInitialized() const {
+  return true;
+}
+
+void StartManagingDeviceResponse::Swap(StartManagingDeviceResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void StartManagingDeviceResponse::InternalSwap(StartManagingDeviceResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(device_uuid_, other->device_uuid_);
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata StartManagingDeviceResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void StopManagingDeviceRequest::InitAsDefaultInstance() {
+}
+class StopManagingDeviceRequest::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int StopManagingDeviceRequest::kNameFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+StopManagingDeviceRequest::StopManagingDeviceRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.StopManagingDeviceRequest)
+}
+StopManagingDeviceRequest::StopManagingDeviceRequest(const StopManagingDeviceRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.name().size() > 0) {
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.StopManagingDeviceRequest)
+}
+
+void StopManagingDeviceRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_StopManagingDeviceRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+StopManagingDeviceRequest::~StopManagingDeviceRequest() {
+  // @@protoc_insertion_point(destructor:dmi.StopManagingDeviceRequest)
+  SharedDtor();
+}
+
+void StopManagingDeviceRequest::SharedDtor() {
+  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void StopManagingDeviceRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const StopManagingDeviceRequest& StopManagingDeviceRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_StopManagingDeviceRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void StopManagingDeviceRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.StopManagingDeviceRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* StopManagingDeviceRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<StopManagingDeviceRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // string name = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.StopManagingDeviceRequest.name");
+        object = msg->mutable_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool StopManagingDeviceRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.StopManagingDeviceRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // string name = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->name().data(), static_cast<int>(this->name().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.StopManagingDeviceRequest.name"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.StopManagingDeviceRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.StopManagingDeviceRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void StopManagingDeviceRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.StopManagingDeviceRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), static_cast<int>(this->name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.StopManagingDeviceRequest.name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->name(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.StopManagingDeviceRequest)
+}
+
+::google::protobuf::uint8* StopManagingDeviceRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.StopManagingDeviceRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string name = 1;
+  if (this->name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->name().data(), static_cast<int>(this->name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.StopManagingDeviceRequest.name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.StopManagingDeviceRequest)
+  return target;
+}
+
+size_t StopManagingDeviceRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.StopManagingDeviceRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string name = 1;
+  if (this->name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->name());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void StopManagingDeviceRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.StopManagingDeviceRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const StopManagingDeviceRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<StopManagingDeviceRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.StopManagingDeviceRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.StopManagingDeviceRequest)
+    MergeFrom(*source);
+  }
+}
+
+void StopManagingDeviceRequest::MergeFrom(const StopManagingDeviceRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.StopManagingDeviceRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.name().size() > 0) {
+
+    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
+  }
+}
+
+void StopManagingDeviceRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.StopManagingDeviceRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void StopManagingDeviceRequest::CopyFrom(const StopManagingDeviceRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.StopManagingDeviceRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool StopManagingDeviceRequest::IsInitialized() const {
+  return true;
+}
+
+void StopManagingDeviceRequest::Swap(StopManagingDeviceRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void StopManagingDeviceRequest::InternalSwap(StopManagingDeviceRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  name_.Swap(&other->name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+}
+
+::google::protobuf::Metadata StopManagingDeviceRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void StopManagingDeviceResponse::InitAsDefaultInstance() {
+}
+class StopManagingDeviceResponse::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int StopManagingDeviceResponse::kStatusFieldNumber;
+const int StopManagingDeviceResponse::kReasonFieldNumber;
+const int StopManagingDeviceResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+StopManagingDeviceResponse::StopManagingDeviceResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.StopManagingDeviceResponse)
+}
+StopManagingDeviceResponse::StopManagingDeviceResponse(const StopManagingDeviceResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.StopManagingDeviceResponse)
+}
+
+void StopManagingDeviceResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_StopManagingDeviceResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+}
+
+StopManagingDeviceResponse::~StopManagingDeviceResponse() {
+  // @@protoc_insertion_point(destructor:dmi.StopManagingDeviceResponse)
+  SharedDtor();
+}
+
+void StopManagingDeviceResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void StopManagingDeviceResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const StopManagingDeviceResponse& StopManagingDeviceResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_StopManagingDeviceResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void StopManagingDeviceResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.StopManagingDeviceResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* StopManagingDeviceResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<StopManagingDeviceResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.StopManagingDeviceResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::StopManagingDeviceResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.StopManagingDeviceResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool StopManagingDeviceResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.StopManagingDeviceResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.StopManagingDeviceResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::StopManagingDeviceResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.StopManagingDeviceResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.StopManagingDeviceResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.StopManagingDeviceResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void StopManagingDeviceResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.StopManagingDeviceResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.StopManagingDeviceResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.StopManagingDeviceResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.StopManagingDeviceResponse)
+}
+
+::google::protobuf::uint8* StopManagingDeviceResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.StopManagingDeviceResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.StopManagingDeviceResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.StopManagingDeviceResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.StopManagingDeviceResponse)
+  return target;
+}
+
+size_t StopManagingDeviceResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.StopManagingDeviceResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.StopManagingDeviceResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void StopManagingDeviceResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.StopManagingDeviceResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const StopManagingDeviceResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<StopManagingDeviceResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.StopManagingDeviceResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.StopManagingDeviceResponse)
+    MergeFrom(*source);
+  }
+}
+
+void StopManagingDeviceResponse::MergeFrom(const StopManagingDeviceResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.StopManagingDeviceResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void StopManagingDeviceResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.StopManagingDeviceResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void StopManagingDeviceResponse::CopyFrom(const StopManagingDeviceResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.StopManagingDeviceResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool StopManagingDeviceResponse::IsInitialized() const {
+  return true;
+}
+
+void StopManagingDeviceResponse::Swap(StopManagingDeviceResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void StopManagingDeviceResponse::InternalSwap(StopManagingDeviceResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata StopManagingDeviceResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ManagedDeviceInfo::InitAsDefaultInstance() {
+  ::dmi::_ManagedDeviceInfo_default_instance_._instance.get_mutable()->info_ = const_cast< ::dmi::ModifiableComponent*>(
+      ::dmi::ModifiableComponent::internal_default_instance());
+  ::dmi::_ManagedDeviceInfo_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class ManagedDeviceInfo::HasBitSetters {
+ public:
+  static const ::dmi::ModifiableComponent& info(const ManagedDeviceInfo* msg);
+  static const ::dmi::Uuid& device_uuid(const ManagedDeviceInfo* msg);
+};
+
+const ::dmi::ModifiableComponent&
+ManagedDeviceInfo::HasBitSetters::info(const ManagedDeviceInfo* msg) {
+  return *msg->info_;
+}
+const ::dmi::Uuid&
+ManagedDeviceInfo::HasBitSetters::device_uuid(const ManagedDeviceInfo* msg) {
+  return *msg->device_uuid_;
+}
+void ManagedDeviceInfo::clear_info() {
+  if (GetArenaNoVirtual() == nullptr && info_ != nullptr) {
+    delete info_;
+  }
+  info_ = nullptr;
+}
+void ManagedDeviceInfo::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ManagedDeviceInfo::kInfoFieldNumber;
+const int ManagedDeviceInfo::kDeviceUuidFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ManagedDeviceInfo::ManagedDeviceInfo()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ManagedDeviceInfo)
+}
+ManagedDeviceInfo::ManagedDeviceInfo(const ManagedDeviceInfo& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_info()) {
+    info_ = new ::dmi::ModifiableComponent(*from.info_);
+  } else {
+    info_ = nullptr;
+  }
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.ManagedDeviceInfo)
+}
+
+void ManagedDeviceInfo::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ManagedDeviceInfo_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::memset(&info_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&device_uuid_) -
+      reinterpret_cast<char*>(&info_)) + sizeof(device_uuid_));
+}
+
+ManagedDeviceInfo::~ManagedDeviceInfo() {
+  // @@protoc_insertion_point(destructor:dmi.ManagedDeviceInfo)
+  SharedDtor();
+}
+
+void ManagedDeviceInfo::SharedDtor() {
+  if (this != internal_default_instance()) delete info_;
+  if (this != internal_default_instance()) delete device_uuid_;
+}
+
+void ManagedDeviceInfo::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ManagedDeviceInfo& ManagedDeviceInfo::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ManagedDeviceInfo_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ManagedDeviceInfo::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ManagedDeviceInfo)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && info_ != nullptr) {
+    delete info_;
+  }
+  info_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ManagedDeviceInfo::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ManagedDeviceInfo*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.ModifiableComponent info = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::ModifiableComponent::_InternalParse;
+        object = msg->mutable_info();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.Uuid device_uuid = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ManagedDeviceInfo::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ManagedDeviceInfo)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.ModifiableComponent info = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_info()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Uuid device_uuid = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ManagedDeviceInfo)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ManagedDeviceInfo)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ManagedDeviceInfo::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ManagedDeviceInfo)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.ModifiableComponent info = 1;
+  if (this->has_info()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::info(this), output);
+  }
+
+  // .dmi.Uuid device_uuid = 2;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::device_uuid(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ManagedDeviceInfo)
+}
+
+::google::protobuf::uint8* ManagedDeviceInfo::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ManagedDeviceInfo)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.ModifiableComponent info = 1;
+  if (this->has_info()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::info(this), target);
+  }
+
+  // .dmi.Uuid device_uuid = 2;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::device_uuid(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ManagedDeviceInfo)
+  return target;
+}
+
+size_t ManagedDeviceInfo::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ManagedDeviceInfo)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.ModifiableComponent info = 1;
+  if (this->has_info()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *info_);
+  }
+
+  // .dmi.Uuid device_uuid = 2;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ManagedDeviceInfo::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ManagedDeviceInfo)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ManagedDeviceInfo* source =
+      ::google::protobuf::DynamicCastToGenerated<ManagedDeviceInfo>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ManagedDeviceInfo)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ManagedDeviceInfo)
+    MergeFrom(*source);
+  }
+}
+
+void ManagedDeviceInfo::MergeFrom(const ManagedDeviceInfo& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ManagedDeviceInfo)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_info()) {
+    mutable_info()->::dmi::ModifiableComponent::MergeFrom(from.info());
+  }
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+}
+
+void ManagedDeviceInfo::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ManagedDeviceInfo)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ManagedDeviceInfo::CopyFrom(const ManagedDeviceInfo& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ManagedDeviceInfo)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ManagedDeviceInfo::IsInitialized() const {
+  return true;
+}
+
+void ManagedDeviceInfo::Swap(ManagedDeviceInfo* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ManagedDeviceInfo::InternalSwap(ManagedDeviceInfo* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(info_, other->info_);
+  swap(device_uuid_, other->device_uuid_);
+}
+
+::google::protobuf::Metadata ManagedDeviceInfo::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ManagedDevicesResponse::InitAsDefaultInstance() {
+}
+class ManagedDevicesResponse::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ManagedDevicesResponse::kStatusFieldNumber;
+const int ManagedDevicesResponse::kReasonFieldNumber;
+const int ManagedDevicesResponse::kDevicesFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ManagedDevicesResponse::ManagedDevicesResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ManagedDevicesResponse)
+}
+ManagedDevicesResponse::ManagedDevicesResponse(const ManagedDevicesResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr),
+      devices_(from.devices_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.ManagedDevicesResponse)
+}
+
+void ManagedDevicesResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ManagedDevicesResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+}
+
+ManagedDevicesResponse::~ManagedDevicesResponse() {
+  // @@protoc_insertion_point(destructor:dmi.ManagedDevicesResponse)
+  SharedDtor();
+}
+
+void ManagedDevicesResponse::SharedDtor() {
+}
+
+void ManagedDevicesResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ManagedDevicesResponse& ManagedDevicesResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ManagedDevicesResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ManagedDevicesResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ManagedDevicesResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  devices_.Clear();
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ManagedDevicesResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ManagedDevicesResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ManagedDevicesResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::ManagedDevicesResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // repeated .dmi.ManagedDeviceInfo devices = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        do {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          parser_till_end = ::dmi::ManagedDeviceInfo::_InternalParse;
+          object = msg->add_devices();
+          if (size > end - ptr) goto len_delim_till_end;
+          ptr += size;
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+              {parser_till_end, object}, ptr - size, ptr));
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 26 && (ptr += 1));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ManagedDevicesResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ManagedDevicesResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ManagedDevicesResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::ManagedDevicesResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // repeated .dmi.ManagedDeviceInfo devices = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+                input, add_devices()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ManagedDevicesResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ManagedDevicesResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ManagedDevicesResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ManagedDevicesResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.ManagedDevicesResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // repeated .dmi.ManagedDeviceInfo devices = 3;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->devices_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3,
+      this->devices(static_cast<int>(i)),
+      output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ManagedDevicesResponse)
+}
+
+::google::protobuf::uint8* ManagedDevicesResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ManagedDevicesResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.ManagedDevicesResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // repeated .dmi.ManagedDeviceInfo devices = 3;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->devices_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, this->devices(static_cast<int>(i)), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ManagedDevicesResponse)
+  return target;
+}
+
+size_t ManagedDevicesResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ManagedDevicesResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated .dmi.ManagedDeviceInfo devices = 3;
+  {
+    unsigned int count = static_cast<unsigned int>(this->devices_size());
+    total_size += 1UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->devices(static_cast<int>(i)));
+    }
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.ManagedDevicesResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ManagedDevicesResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ManagedDevicesResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ManagedDevicesResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<ManagedDevicesResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ManagedDevicesResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ManagedDevicesResponse)
+    MergeFrom(*source);
+  }
+}
+
+void ManagedDevicesResponse::MergeFrom(const ManagedDevicesResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ManagedDevicesResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  devices_.MergeFrom(from.devices_);
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void ManagedDevicesResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ManagedDevicesResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ManagedDevicesResponse::CopyFrom(const ManagedDevicesResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ManagedDevicesResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ManagedDevicesResponse::IsInitialized() const {
+  return true;
+}
+
+void ManagedDevicesResponse::Swap(ManagedDevicesResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ManagedDevicesResponse::InternalSwap(ManagedDevicesResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  CastToBase(&devices_)->InternalSwap(CastToBase(&other->devices_));
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata ManagedDevicesResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void SetLoggingEndpointRequest::InitAsDefaultInstance() {
+  ::dmi::_SetLoggingEndpointRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class SetLoggingEndpointRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const SetLoggingEndpointRequest* msg);
+};
+
+const ::dmi::Uuid&
+SetLoggingEndpointRequest::HasBitSetters::device_uuid(const SetLoggingEndpointRequest* msg) {
+  return *msg->device_uuid_;
+}
+void SetLoggingEndpointRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int SetLoggingEndpointRequest::kDeviceUuidFieldNumber;
+const int SetLoggingEndpointRequest::kLoggingEndpointFieldNumber;
+const int SetLoggingEndpointRequest::kLoggingProtocolFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+SetLoggingEndpointRequest::SetLoggingEndpointRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.SetLoggingEndpointRequest)
+}
+SetLoggingEndpointRequest::SetLoggingEndpointRequest(const SetLoggingEndpointRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  logging_endpoint_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.logging_endpoint().size() > 0) {
+    logging_endpoint_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.logging_endpoint_);
+  }
+  logging_protocol_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.logging_protocol().size() > 0) {
+    logging_protocol_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.logging_protocol_);
+  }
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.SetLoggingEndpointRequest)
+}
+
+void SetLoggingEndpointRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_SetLoggingEndpointRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  logging_endpoint_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  logging_protocol_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  device_uuid_ = nullptr;
+}
+
+SetLoggingEndpointRequest::~SetLoggingEndpointRequest() {
+  // @@protoc_insertion_point(destructor:dmi.SetLoggingEndpointRequest)
+  SharedDtor();
+}
+
+void SetLoggingEndpointRequest::SharedDtor() {
+  logging_endpoint_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  logging_protocol_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete device_uuid_;
+}
+
+void SetLoggingEndpointRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const SetLoggingEndpointRequest& SetLoggingEndpointRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_SetLoggingEndpointRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void SetLoggingEndpointRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.SetLoggingEndpointRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  logging_endpoint_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  logging_protocol_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* SetLoggingEndpointRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<SetLoggingEndpointRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string logging_endpoint = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.SetLoggingEndpointRequest.logging_endpoint");
+        object = msg->mutable_logging_endpoint();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string logging_protocol = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.SetLoggingEndpointRequest.logging_protocol");
+        object = msg->mutable_logging_protocol();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool SetLoggingEndpointRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.SetLoggingEndpointRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string logging_endpoint = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_logging_endpoint()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->logging_endpoint().data(), static_cast<int>(this->logging_endpoint().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.SetLoggingEndpointRequest.logging_endpoint"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string logging_protocol = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_logging_protocol()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->logging_protocol().data(), static_cast<int>(this->logging_protocol().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.SetLoggingEndpointRequest.logging_protocol"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.SetLoggingEndpointRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.SetLoggingEndpointRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void SetLoggingEndpointRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.SetLoggingEndpointRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // string logging_endpoint = 2;
+  if (this->logging_endpoint().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->logging_endpoint().data(), static_cast<int>(this->logging_endpoint().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.SetLoggingEndpointRequest.logging_endpoint");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      2, this->logging_endpoint(), output);
+  }
+
+  // string logging_protocol = 3;
+  if (this->logging_protocol().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->logging_protocol().data(), static_cast<int>(this->logging_protocol().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.SetLoggingEndpointRequest.logging_protocol");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->logging_protocol(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.SetLoggingEndpointRequest)
+}
+
+::google::protobuf::uint8* SetLoggingEndpointRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.SetLoggingEndpointRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // string logging_endpoint = 2;
+  if (this->logging_endpoint().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->logging_endpoint().data(), static_cast<int>(this->logging_endpoint().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.SetLoggingEndpointRequest.logging_endpoint");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->logging_endpoint(), target);
+  }
+
+  // string logging_protocol = 3;
+  if (this->logging_protocol().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->logging_protocol().data(), static_cast<int>(this->logging_protocol().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.SetLoggingEndpointRequest.logging_protocol");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->logging_protocol(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.SetLoggingEndpointRequest)
+  return target;
+}
+
+size_t SetLoggingEndpointRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.SetLoggingEndpointRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string logging_endpoint = 2;
+  if (this->logging_endpoint().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->logging_endpoint());
+  }
+
+  // string logging_protocol = 3;
+  if (this->logging_protocol().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->logging_protocol());
+  }
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void SetLoggingEndpointRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.SetLoggingEndpointRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const SetLoggingEndpointRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<SetLoggingEndpointRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.SetLoggingEndpointRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.SetLoggingEndpointRequest)
+    MergeFrom(*source);
+  }
+}
+
+void SetLoggingEndpointRequest::MergeFrom(const SetLoggingEndpointRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.SetLoggingEndpointRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.logging_endpoint().size() > 0) {
+
+    logging_endpoint_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.logging_endpoint_);
+  }
+  if (from.logging_protocol().size() > 0) {
+
+    logging_protocol_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.logging_protocol_);
+  }
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+}
+
+void SetLoggingEndpointRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.SetLoggingEndpointRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SetLoggingEndpointRequest::CopyFrom(const SetLoggingEndpointRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.SetLoggingEndpointRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SetLoggingEndpointRequest::IsInitialized() const {
+  return true;
+}
+
+void SetLoggingEndpointRequest::Swap(SetLoggingEndpointRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void SetLoggingEndpointRequest::InternalSwap(SetLoggingEndpointRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  logging_endpoint_.Swap(&other->logging_endpoint_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  logging_protocol_.Swap(&other->logging_protocol_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(device_uuid_, other->device_uuid_);
+}
+
+::google::protobuf::Metadata SetLoggingEndpointRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void SetRemoteEndpointResponse::InitAsDefaultInstance() {
+}
+class SetRemoteEndpointResponse::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int SetRemoteEndpointResponse::kStatusFieldNumber;
+const int SetRemoteEndpointResponse::kReasonFieldNumber;
+const int SetRemoteEndpointResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+SetRemoteEndpointResponse::SetRemoteEndpointResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.SetRemoteEndpointResponse)
+}
+SetRemoteEndpointResponse::SetRemoteEndpointResponse(const SetRemoteEndpointResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.SetRemoteEndpointResponse)
+}
+
+void SetRemoteEndpointResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_SetRemoteEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+}
+
+SetRemoteEndpointResponse::~SetRemoteEndpointResponse() {
+  // @@protoc_insertion_point(destructor:dmi.SetRemoteEndpointResponse)
+  SharedDtor();
+}
+
+void SetRemoteEndpointResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void SetRemoteEndpointResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const SetRemoteEndpointResponse& SetRemoteEndpointResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_SetRemoteEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void SetRemoteEndpointResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.SetRemoteEndpointResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* SetRemoteEndpointResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<SetRemoteEndpointResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.SetRemoteEndpointResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::SetRemoteEndpointResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.SetRemoteEndpointResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool SetRemoteEndpointResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.SetRemoteEndpointResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.SetRemoteEndpointResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::SetRemoteEndpointResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.SetRemoteEndpointResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.SetRemoteEndpointResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.SetRemoteEndpointResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void SetRemoteEndpointResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.SetRemoteEndpointResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.SetRemoteEndpointResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.SetRemoteEndpointResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.SetRemoteEndpointResponse)
+}
+
+::google::protobuf::uint8* SetRemoteEndpointResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.SetRemoteEndpointResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.SetRemoteEndpointResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.SetRemoteEndpointResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.SetRemoteEndpointResponse)
+  return target;
+}
+
+size_t SetRemoteEndpointResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.SetRemoteEndpointResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.SetRemoteEndpointResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void SetRemoteEndpointResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.SetRemoteEndpointResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const SetRemoteEndpointResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<SetRemoteEndpointResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.SetRemoteEndpointResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.SetRemoteEndpointResponse)
+    MergeFrom(*source);
+  }
+}
+
+void SetRemoteEndpointResponse::MergeFrom(const SetRemoteEndpointResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.SetRemoteEndpointResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void SetRemoteEndpointResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.SetRemoteEndpointResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SetRemoteEndpointResponse::CopyFrom(const SetRemoteEndpointResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.SetRemoteEndpointResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SetRemoteEndpointResponse::IsInitialized() const {
+  return true;
+}
+
+void SetRemoteEndpointResponse::Swap(SetRemoteEndpointResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void SetRemoteEndpointResponse::InternalSwap(SetRemoteEndpointResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata SetRemoteEndpointResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void GetLoggingEndpointResponse::InitAsDefaultInstance() {
+}
+class GetLoggingEndpointResponse::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GetLoggingEndpointResponse::kStatusFieldNumber;
+const int GetLoggingEndpointResponse::kReasonFieldNumber;
+const int GetLoggingEndpointResponse::kLoggingEndpointFieldNumber;
+const int GetLoggingEndpointResponse::kLoggingProtocolFieldNumber;
+const int GetLoggingEndpointResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GetLoggingEndpointResponse::GetLoggingEndpointResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.GetLoggingEndpointResponse)
+}
+GetLoggingEndpointResponse::GetLoggingEndpointResponse(const GetLoggingEndpointResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  logging_endpoint_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.logging_endpoint().size() > 0) {
+    logging_endpoint_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.logging_endpoint_);
+  }
+  logging_protocol_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.logging_protocol().size() > 0) {
+    logging_protocol_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.logging_protocol_);
+  }
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.GetLoggingEndpointResponse)
+}
+
+void GetLoggingEndpointResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_GetLoggingEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  logging_endpoint_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  logging_protocol_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+}
+
+GetLoggingEndpointResponse::~GetLoggingEndpointResponse() {
+  // @@protoc_insertion_point(destructor:dmi.GetLoggingEndpointResponse)
+  SharedDtor();
+}
+
+void GetLoggingEndpointResponse::SharedDtor() {
+  logging_endpoint_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  logging_protocol_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void GetLoggingEndpointResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const GetLoggingEndpointResponse& GetLoggingEndpointResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_GetLoggingEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void GetLoggingEndpointResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.GetLoggingEndpointResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  logging_endpoint_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  logging_protocol_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* GetLoggingEndpointResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<GetLoggingEndpointResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.GetLoggingEndpointResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::GetLoggingEndpointResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string logging_endpoint = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.GetLoggingEndpointResponse.logging_endpoint");
+        object = msg->mutable_logging_endpoint();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string logging_protocol = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.GetLoggingEndpointResponse.logging_protocol");
+        object = msg->mutable_logging_protocol();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string reason_detail = 5;
+      case 5: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.GetLoggingEndpointResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool GetLoggingEndpointResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.GetLoggingEndpointResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.GetLoggingEndpointResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::GetLoggingEndpointResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string logging_endpoint = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_logging_endpoint()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->logging_endpoint().data(), static_cast<int>(this->logging_endpoint().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.GetLoggingEndpointResponse.logging_endpoint"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string logging_protocol = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_logging_protocol()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->logging_protocol().data(), static_cast<int>(this->logging_protocol().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.GetLoggingEndpointResponse.logging_protocol"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 5;
+      case 5: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (42 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.GetLoggingEndpointResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.GetLoggingEndpointResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.GetLoggingEndpointResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void GetLoggingEndpointResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.GetLoggingEndpointResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.GetLoggingEndpointResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // string logging_endpoint = 3;
+  if (this->logging_endpoint().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->logging_endpoint().data(), static_cast<int>(this->logging_endpoint().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetLoggingEndpointResponse.logging_endpoint");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->logging_endpoint(), output);
+  }
+
+  // string logging_protocol = 4;
+  if (this->logging_protocol().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->logging_protocol().data(), static_cast<int>(this->logging_protocol().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetLoggingEndpointResponse.logging_protocol");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->logging_protocol(), output);
+  }
+
+  // string reason_detail = 5;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetLoggingEndpointResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      5, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.GetLoggingEndpointResponse)
+}
+
+::google::protobuf::uint8* GetLoggingEndpointResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetLoggingEndpointResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.GetLoggingEndpointResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // string logging_endpoint = 3;
+  if (this->logging_endpoint().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->logging_endpoint().data(), static_cast<int>(this->logging_endpoint().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetLoggingEndpointResponse.logging_endpoint");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->logging_endpoint(), target);
+  }
+
+  // string logging_protocol = 4;
+  if (this->logging_protocol().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->logging_protocol().data(), static_cast<int>(this->logging_protocol().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetLoggingEndpointResponse.logging_protocol");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->logging_protocol(), target);
+  }
+
+  // string reason_detail = 5;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetLoggingEndpointResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        5, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetLoggingEndpointResponse)
+  return target;
+}
+
+size_t GetLoggingEndpointResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.GetLoggingEndpointResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string logging_endpoint = 3;
+  if (this->logging_endpoint().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->logging_endpoint());
+  }
+
+  // string logging_protocol = 4;
+  if (this->logging_protocol().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->logging_protocol());
+  }
+
+  // string reason_detail = 5;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.GetLoggingEndpointResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void GetLoggingEndpointResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetLoggingEndpointResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const GetLoggingEndpointResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<GetLoggingEndpointResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetLoggingEndpointResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetLoggingEndpointResponse)
+    MergeFrom(*source);
+  }
+}
+
+void GetLoggingEndpointResponse::MergeFrom(const GetLoggingEndpointResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetLoggingEndpointResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.logging_endpoint().size() > 0) {
+
+    logging_endpoint_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.logging_endpoint_);
+  }
+  if (from.logging_protocol().size() > 0) {
+
+    logging_protocol_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.logging_protocol_);
+  }
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void GetLoggingEndpointResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetLoggingEndpointResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GetLoggingEndpointResponse::CopyFrom(const GetLoggingEndpointResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.GetLoggingEndpointResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetLoggingEndpointResponse::IsInitialized() const {
+  return true;
+}
+
+void GetLoggingEndpointResponse::Swap(GetLoggingEndpointResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void GetLoggingEndpointResponse::InternalSwap(GetLoggingEndpointResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  logging_endpoint_.Swap(&other->logging_endpoint_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  logging_protocol_.Swap(&other->logging_protocol_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata GetLoggingEndpointResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void SetMsgBusEndpointRequest::InitAsDefaultInstance() {
+}
+class SetMsgBusEndpointRequest::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int SetMsgBusEndpointRequest::kMsgbusEndpointFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+SetMsgBusEndpointRequest::SetMsgBusEndpointRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.SetMsgBusEndpointRequest)
+}
+SetMsgBusEndpointRequest::SetMsgBusEndpointRequest(const SetMsgBusEndpointRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  msgbus_endpoint_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.msgbus_endpoint().size() > 0) {
+    msgbus_endpoint_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.msgbus_endpoint_);
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.SetMsgBusEndpointRequest)
+}
+
+void SetMsgBusEndpointRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_SetMsgBusEndpointRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  msgbus_endpoint_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+SetMsgBusEndpointRequest::~SetMsgBusEndpointRequest() {
+  // @@protoc_insertion_point(destructor:dmi.SetMsgBusEndpointRequest)
+  SharedDtor();
+}
+
+void SetMsgBusEndpointRequest::SharedDtor() {
+  msgbus_endpoint_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void SetMsgBusEndpointRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const SetMsgBusEndpointRequest& SetMsgBusEndpointRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_SetMsgBusEndpointRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void SetMsgBusEndpointRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.SetMsgBusEndpointRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  msgbus_endpoint_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* SetMsgBusEndpointRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<SetMsgBusEndpointRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // string msgbus_endpoint = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.SetMsgBusEndpointRequest.msgbus_endpoint");
+        object = msg->mutable_msgbus_endpoint();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool SetMsgBusEndpointRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.SetMsgBusEndpointRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // string msgbus_endpoint = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_msgbus_endpoint()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->msgbus_endpoint().data(), static_cast<int>(this->msgbus_endpoint().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.SetMsgBusEndpointRequest.msgbus_endpoint"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.SetMsgBusEndpointRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.SetMsgBusEndpointRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void SetMsgBusEndpointRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.SetMsgBusEndpointRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string msgbus_endpoint = 1;
+  if (this->msgbus_endpoint().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->msgbus_endpoint().data(), static_cast<int>(this->msgbus_endpoint().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.SetMsgBusEndpointRequest.msgbus_endpoint");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->msgbus_endpoint(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.SetMsgBusEndpointRequest)
+}
+
+::google::protobuf::uint8* SetMsgBusEndpointRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.SetMsgBusEndpointRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string msgbus_endpoint = 1;
+  if (this->msgbus_endpoint().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->msgbus_endpoint().data(), static_cast<int>(this->msgbus_endpoint().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.SetMsgBusEndpointRequest.msgbus_endpoint");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->msgbus_endpoint(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.SetMsgBusEndpointRequest)
+  return target;
+}
+
+size_t SetMsgBusEndpointRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.SetMsgBusEndpointRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string msgbus_endpoint = 1;
+  if (this->msgbus_endpoint().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->msgbus_endpoint());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void SetMsgBusEndpointRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.SetMsgBusEndpointRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const SetMsgBusEndpointRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<SetMsgBusEndpointRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.SetMsgBusEndpointRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.SetMsgBusEndpointRequest)
+    MergeFrom(*source);
+  }
+}
+
+void SetMsgBusEndpointRequest::MergeFrom(const SetMsgBusEndpointRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.SetMsgBusEndpointRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.msgbus_endpoint().size() > 0) {
+
+    msgbus_endpoint_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.msgbus_endpoint_);
+  }
+}
+
+void SetMsgBusEndpointRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.SetMsgBusEndpointRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SetMsgBusEndpointRequest::CopyFrom(const SetMsgBusEndpointRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.SetMsgBusEndpointRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SetMsgBusEndpointRequest::IsInitialized() const {
+  return true;
+}
+
+void SetMsgBusEndpointRequest::Swap(SetMsgBusEndpointRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void SetMsgBusEndpointRequest::InternalSwap(SetMsgBusEndpointRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  msgbus_endpoint_.Swap(&other->msgbus_endpoint_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+}
+
+::google::protobuf::Metadata SetMsgBusEndpointRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void GetMsgBusEndpointResponse::InitAsDefaultInstance() {
+}
+class GetMsgBusEndpointResponse::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GetMsgBusEndpointResponse::kStatusFieldNumber;
+const int GetMsgBusEndpointResponse::kReasonFieldNumber;
+const int GetMsgBusEndpointResponse::kMsgbusEndpointFieldNumber;
+const int GetMsgBusEndpointResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GetMsgBusEndpointResponse::GetMsgBusEndpointResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.GetMsgBusEndpointResponse)
+}
+GetMsgBusEndpointResponse::GetMsgBusEndpointResponse(const GetMsgBusEndpointResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  msgbus_endpoint_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.msgbus_endpoint().size() > 0) {
+    msgbus_endpoint_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.msgbus_endpoint_);
+  }
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.GetMsgBusEndpointResponse)
+}
+
+void GetMsgBusEndpointResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_GetMsgBusEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  msgbus_endpoint_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+}
+
+GetMsgBusEndpointResponse::~GetMsgBusEndpointResponse() {
+  // @@protoc_insertion_point(destructor:dmi.GetMsgBusEndpointResponse)
+  SharedDtor();
+}
+
+void GetMsgBusEndpointResponse::SharedDtor() {
+  msgbus_endpoint_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void GetMsgBusEndpointResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const GetMsgBusEndpointResponse& GetMsgBusEndpointResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_GetMsgBusEndpointResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void GetMsgBusEndpointResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.GetMsgBusEndpointResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  msgbus_endpoint_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* GetMsgBusEndpointResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<GetMsgBusEndpointResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.GetMsgBusEndpointResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::GetMsgBusEndpointResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string msgbus_endpoint = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.GetMsgBusEndpointResponse.msgbus_endpoint");
+        object = msg->mutable_msgbus_endpoint();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.GetMsgBusEndpointResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool GetMsgBusEndpointResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.GetMsgBusEndpointResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.GetMsgBusEndpointResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::GetMsgBusEndpointResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string msgbus_endpoint = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_msgbus_endpoint()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->msgbus_endpoint().data(), static_cast<int>(this->msgbus_endpoint().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.GetMsgBusEndpointResponse.msgbus_endpoint"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.GetMsgBusEndpointResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.GetMsgBusEndpointResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.GetMsgBusEndpointResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void GetMsgBusEndpointResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.GetMsgBusEndpointResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.GetMsgBusEndpointResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // string msgbus_endpoint = 3;
+  if (this->msgbus_endpoint().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->msgbus_endpoint().data(), static_cast<int>(this->msgbus_endpoint().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetMsgBusEndpointResponse.msgbus_endpoint");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->msgbus_endpoint(), output);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetMsgBusEndpointResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.GetMsgBusEndpointResponse)
+}
+
+::google::protobuf::uint8* GetMsgBusEndpointResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetMsgBusEndpointResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.GetMsgBusEndpointResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // string msgbus_endpoint = 3;
+  if (this->msgbus_endpoint().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->msgbus_endpoint().data(), static_cast<int>(this->msgbus_endpoint().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetMsgBusEndpointResponse.msgbus_endpoint");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->msgbus_endpoint(), target);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetMsgBusEndpointResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetMsgBusEndpointResponse)
+  return target;
+}
+
+size_t GetMsgBusEndpointResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.GetMsgBusEndpointResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string msgbus_endpoint = 3;
+  if (this->msgbus_endpoint().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->msgbus_endpoint());
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.GetMsgBusEndpointResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void GetMsgBusEndpointResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetMsgBusEndpointResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const GetMsgBusEndpointResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<GetMsgBusEndpointResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetMsgBusEndpointResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetMsgBusEndpointResponse)
+    MergeFrom(*source);
+  }
+}
+
+void GetMsgBusEndpointResponse::MergeFrom(const GetMsgBusEndpointResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetMsgBusEndpointResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.msgbus_endpoint().size() > 0) {
+
+    msgbus_endpoint_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.msgbus_endpoint_);
+  }
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void GetMsgBusEndpointResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetMsgBusEndpointResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GetMsgBusEndpointResponse::CopyFrom(const GetMsgBusEndpointResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.GetMsgBusEndpointResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetMsgBusEndpointResponse::IsInitialized() const {
+  return true;
+}
+
+void GetMsgBusEndpointResponse::Swap(GetMsgBusEndpointResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void GetMsgBusEndpointResponse::InternalSwap(GetMsgBusEndpointResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  msgbus_endpoint_.Swap(&other->msgbus_endpoint_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata GetMsgBusEndpointResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void EntitiesLogLevel::InitAsDefaultInstance() {
+}
+class EntitiesLogLevel::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int EntitiesLogLevel::kLogLevelFieldNumber;
+const int EntitiesLogLevel::kEntitiesFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+EntitiesLogLevel::EntitiesLogLevel()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.EntitiesLogLevel)
+}
+EntitiesLogLevel::EntitiesLogLevel(const EntitiesLogLevel& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr),
+      entities_(from.entities_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  loglevel_ = from.loglevel_;
+  // @@protoc_insertion_point(copy_constructor:dmi.EntitiesLogLevel)
+}
+
+void EntitiesLogLevel::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_EntitiesLogLevel_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  loglevel_ = 0;
+}
+
+EntitiesLogLevel::~EntitiesLogLevel() {
+  // @@protoc_insertion_point(destructor:dmi.EntitiesLogLevel)
+  SharedDtor();
+}
+
+void EntitiesLogLevel::SharedDtor() {
+}
+
+void EntitiesLogLevel::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const EntitiesLogLevel& EntitiesLogLevel::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_EntitiesLogLevel_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void EntitiesLogLevel::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.EntitiesLogLevel)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  entities_.Clear();
+  loglevel_ = 0;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* EntitiesLogLevel::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<EntitiesLogLevel*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.LogLevel logLevel = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_loglevel(static_cast<::dmi::LogLevel>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // repeated string entities = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        do {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          ctx->extra_parse_data().SetFieldName("dmi.EntitiesLogLevel.entities");
+          object = msg->add_entities();
+          if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+            parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+            goto string_till_end;
+          }
+          GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+          ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+          ptr += size;
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 18 && (ptr += 1));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool EntitiesLogLevel::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.EntitiesLogLevel)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.LogLevel logLevel = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_loglevel(static_cast< ::dmi::LogLevel >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // repeated string entities = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->add_entities()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->entities(this->entities_size() - 1).data(),
+            static_cast<int>(this->entities(this->entities_size() - 1).length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.EntitiesLogLevel.entities"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.EntitiesLogLevel)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.EntitiesLogLevel)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void EntitiesLogLevel::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.EntitiesLogLevel)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.LogLevel logLevel = 1;
+  if (this->loglevel() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->loglevel(), output);
+  }
+
+  // repeated string entities = 2;
+  for (int i = 0, n = this->entities_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->entities(i).data(), static_cast<int>(this->entities(i).length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.EntitiesLogLevel.entities");
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      2, this->entities(i), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.EntitiesLogLevel)
+}
+
+::google::protobuf::uint8* EntitiesLogLevel::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.EntitiesLogLevel)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.LogLevel logLevel = 1;
+  if (this->loglevel() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->loglevel(), target);
+  }
+
+  // repeated string entities = 2;
+  for (int i = 0, n = this->entities_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->entities(i).data(), static_cast<int>(this->entities(i).length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.EntitiesLogLevel.entities");
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteStringToArray(2, this->entities(i), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.EntitiesLogLevel)
+  return target;
+}
+
+size_t EntitiesLogLevel::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.EntitiesLogLevel)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated string entities = 2;
+  total_size += 1 *
+      ::google::protobuf::internal::FromIntSize(this->entities_size());
+  for (int i = 0, n = this->entities_size(); i < n; i++) {
+    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+      this->entities(i));
+  }
+
+  // .dmi.LogLevel logLevel = 1;
+  if (this->loglevel() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->loglevel());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void EntitiesLogLevel::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.EntitiesLogLevel)
+  GOOGLE_DCHECK_NE(&from, this);
+  const EntitiesLogLevel* source =
+      ::google::protobuf::DynamicCastToGenerated<EntitiesLogLevel>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.EntitiesLogLevel)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.EntitiesLogLevel)
+    MergeFrom(*source);
+  }
+}
+
+void EntitiesLogLevel::MergeFrom(const EntitiesLogLevel& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.EntitiesLogLevel)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  entities_.MergeFrom(from.entities_);
+  if (from.loglevel() != 0) {
+    set_loglevel(from.loglevel());
+  }
+}
+
+void EntitiesLogLevel::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.EntitiesLogLevel)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EntitiesLogLevel::CopyFrom(const EntitiesLogLevel& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.EntitiesLogLevel)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool EntitiesLogLevel::IsInitialized() const {
+  return true;
+}
+
+void EntitiesLogLevel::Swap(EntitiesLogLevel* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void EntitiesLogLevel::InternalSwap(EntitiesLogLevel* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  entities_.InternalSwap(CastToBase(&other->entities_));
+  swap(loglevel_, other->loglevel_);
+}
+
+::google::protobuf::Metadata EntitiesLogLevel::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void SetLogLevelRequest::InitAsDefaultInstance() {
+  ::dmi::_SetLogLevelRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class SetLogLevelRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const SetLogLevelRequest* msg);
+};
+
+const ::dmi::Uuid&
+SetLogLevelRequest::HasBitSetters::device_uuid(const SetLogLevelRequest* msg) {
+  return *msg->device_uuid_;
+}
+void SetLogLevelRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int SetLogLevelRequest::kDeviceUuidFieldNumber;
+const int SetLogLevelRequest::kLoglevelsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+SetLogLevelRequest::SetLogLevelRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.SetLogLevelRequest)
+}
+SetLogLevelRequest::SetLogLevelRequest(const SetLogLevelRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr),
+      loglevels_(from.loglevels_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.SetLogLevelRequest)
+}
+
+void SetLogLevelRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_SetLogLevelRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  device_uuid_ = nullptr;
+}
+
+SetLogLevelRequest::~SetLogLevelRequest() {
+  // @@protoc_insertion_point(destructor:dmi.SetLogLevelRequest)
+  SharedDtor();
+}
+
+void SetLogLevelRequest::SharedDtor() {
+  if (this != internal_default_instance()) delete device_uuid_;
+}
+
+void SetLogLevelRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const SetLogLevelRequest& SetLogLevelRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_SetLogLevelRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void SetLogLevelRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.SetLogLevelRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  loglevels_.Clear();
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* SetLogLevelRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<SetLogLevelRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // repeated .dmi.EntitiesLogLevel loglevels = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        do {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          parser_till_end = ::dmi::EntitiesLogLevel::_InternalParse;
+          object = msg->add_loglevels();
+          if (size > end - ptr) goto len_delim_till_end;
+          ptr += size;
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+              {parser_till_end, object}, ptr - size, ptr));
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 18 && (ptr += 1));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool SetLogLevelRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.SetLogLevelRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // repeated .dmi.EntitiesLogLevel loglevels = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+                input, add_loglevels()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.SetLogLevelRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.SetLogLevelRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void SetLogLevelRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.SetLogLevelRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // repeated .dmi.EntitiesLogLevel loglevels = 2;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->loglevels_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2,
+      this->loglevels(static_cast<int>(i)),
+      output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.SetLogLevelRequest)
+}
+
+::google::protobuf::uint8* SetLogLevelRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.SetLogLevelRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // repeated .dmi.EntitiesLogLevel loglevels = 2;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->loglevels_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, this->loglevels(static_cast<int>(i)), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.SetLogLevelRequest)
+  return target;
+}
+
+size_t SetLogLevelRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.SetLogLevelRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated .dmi.EntitiesLogLevel loglevels = 2;
+  {
+    unsigned int count = static_cast<unsigned int>(this->loglevels_size());
+    total_size += 1UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->loglevels(static_cast<int>(i)));
+    }
+  }
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void SetLogLevelRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.SetLogLevelRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const SetLogLevelRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<SetLogLevelRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.SetLogLevelRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.SetLogLevelRequest)
+    MergeFrom(*source);
+  }
+}
+
+void SetLogLevelRequest::MergeFrom(const SetLogLevelRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.SetLogLevelRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  loglevels_.MergeFrom(from.loglevels_);
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+}
+
+void SetLogLevelRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.SetLogLevelRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SetLogLevelRequest::CopyFrom(const SetLogLevelRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.SetLogLevelRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SetLogLevelRequest::IsInitialized() const {
+  return true;
+}
+
+void SetLogLevelRequest::Swap(SetLogLevelRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void SetLogLevelRequest::InternalSwap(SetLogLevelRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  CastToBase(&loglevels_)->InternalSwap(CastToBase(&other->loglevels_));
+  swap(device_uuid_, other->device_uuid_);
+}
+
+::google::protobuf::Metadata SetLogLevelRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void SetLogLevelResponse::InitAsDefaultInstance() {
+  ::dmi::_SetLogLevelResponse_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class SetLogLevelResponse::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const SetLogLevelResponse* msg);
+};
+
+const ::dmi::Uuid&
+SetLogLevelResponse::HasBitSetters::device_uuid(const SetLogLevelResponse* msg) {
+  return *msg->device_uuid_;
+}
+void SetLogLevelResponse::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int SetLogLevelResponse::kDeviceUuidFieldNumber;
+const int SetLogLevelResponse::kStatusFieldNumber;
+const int SetLogLevelResponse::kReasonFieldNumber;
+const int SetLogLevelResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+SetLogLevelResponse::SetLogLevelResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.SetLogLevelResponse)
+}
+SetLogLevelResponse::SetLogLevelResponse(const SetLogLevelResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.SetLogLevelResponse)
+}
+
+void SetLogLevelResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_SetLogLevelResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&device_uuid_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&device_uuid_)) + sizeof(reason_));
+}
+
+SetLogLevelResponse::~SetLogLevelResponse() {
+  // @@protoc_insertion_point(destructor:dmi.SetLogLevelResponse)
+  SharedDtor();
+}
+
+void SetLogLevelResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete device_uuid_;
+}
+
+void SetLogLevelResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const SetLogLevelResponse& SetLogLevelResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_SetLogLevelResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void SetLogLevelResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.SetLogLevelResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* SetLogLevelResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<SetLogLevelResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.Status status = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.SetLogLevelResponse.Reason reason = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::SetLogLevelResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.SetLogLevelResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool SetLogLevelResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.SetLogLevelResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Status status = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.SetLogLevelResponse.Reason reason = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::SetLogLevelResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.SetLogLevelResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.SetLogLevelResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.SetLogLevelResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void SetLogLevelResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.SetLogLevelResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // .dmi.Status status = 2;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->status(), output);
+  }
+
+  // .dmi.SetLogLevelResponse.Reason reason = 3;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      3, this->reason(), output);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.SetLogLevelResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.SetLogLevelResponse)
+}
+
+::google::protobuf::uint8* SetLogLevelResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.SetLogLevelResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // .dmi.Status status = 2;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->status(), target);
+  }
+
+  // .dmi.SetLogLevelResponse.Reason reason = 3;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      3, this->reason(), target);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.SetLogLevelResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.SetLogLevelResponse)
+  return target;
+}
+
+size_t SetLogLevelResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.SetLogLevelResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  // .dmi.Status status = 2;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.SetLogLevelResponse.Reason reason = 3;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void SetLogLevelResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.SetLogLevelResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const SetLogLevelResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<SetLogLevelResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.SetLogLevelResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.SetLogLevelResponse)
+    MergeFrom(*source);
+  }
+}
+
+void SetLogLevelResponse::MergeFrom(const SetLogLevelResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.SetLogLevelResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void SetLogLevelResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.SetLogLevelResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SetLogLevelResponse::CopyFrom(const SetLogLevelResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.SetLogLevelResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SetLogLevelResponse::IsInitialized() const {
+  return true;
+}
+
+void SetLogLevelResponse::Swap(SetLogLevelResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void SetLogLevelResponse::InternalSwap(SetLogLevelResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(device_uuid_, other->device_uuid_);
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata SetLogLevelResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void GetLogLevelRequest::InitAsDefaultInstance() {
+  ::dmi::_GetLogLevelRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class GetLogLevelRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const GetLogLevelRequest* msg);
+};
+
+const ::dmi::Uuid&
+GetLogLevelRequest::HasBitSetters::device_uuid(const GetLogLevelRequest* msg) {
+  return *msg->device_uuid_;
+}
+void GetLogLevelRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GetLogLevelRequest::kDeviceUuidFieldNumber;
+const int GetLogLevelRequest::kEntitiesFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GetLogLevelRequest::GetLogLevelRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.GetLogLevelRequest)
+}
+GetLogLevelRequest::GetLogLevelRequest(const GetLogLevelRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr),
+      entities_(from.entities_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.GetLogLevelRequest)
+}
+
+void GetLogLevelRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_GetLogLevelRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  device_uuid_ = nullptr;
+}
+
+GetLogLevelRequest::~GetLogLevelRequest() {
+  // @@protoc_insertion_point(destructor:dmi.GetLogLevelRequest)
+  SharedDtor();
+}
+
+void GetLogLevelRequest::SharedDtor() {
+  if (this != internal_default_instance()) delete device_uuid_;
+}
+
+void GetLogLevelRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const GetLogLevelRequest& GetLogLevelRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_GetLogLevelRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void GetLogLevelRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.GetLogLevelRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  entities_.Clear();
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* GetLogLevelRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<GetLogLevelRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // repeated string entities = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        do {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          ctx->extra_parse_data().SetFieldName("dmi.GetLogLevelRequest.entities");
+          object = msg->add_entities();
+          if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+            parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+            goto string_till_end;
+          }
+          GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+          ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+          ptr += size;
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 18 && (ptr += 1));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool GetLogLevelRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.GetLogLevelRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // repeated string entities = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->add_entities()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->entities(this->entities_size() - 1).data(),
+            static_cast<int>(this->entities(this->entities_size() - 1).length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.GetLogLevelRequest.entities"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.GetLogLevelRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.GetLogLevelRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void GetLogLevelRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.GetLogLevelRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // repeated string entities = 2;
+  for (int i = 0, n = this->entities_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->entities(i).data(), static_cast<int>(this->entities(i).length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetLogLevelRequest.entities");
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      2, this->entities(i), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.GetLogLevelRequest)
+}
+
+::google::protobuf::uint8* GetLogLevelRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetLogLevelRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // repeated string entities = 2;
+  for (int i = 0, n = this->entities_size(); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->entities(i).data(), static_cast<int>(this->entities(i).length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetLogLevelRequest.entities");
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteStringToArray(2, this->entities(i), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetLogLevelRequest)
+  return target;
+}
+
+size_t GetLogLevelRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.GetLogLevelRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated string entities = 2;
+  total_size += 1 *
+      ::google::protobuf::internal::FromIntSize(this->entities_size());
+  for (int i = 0, n = this->entities_size(); i < n; i++) {
+    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+      this->entities(i));
+  }
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void GetLogLevelRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetLogLevelRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const GetLogLevelRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<GetLogLevelRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetLogLevelRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetLogLevelRequest)
+    MergeFrom(*source);
+  }
+}
+
+void GetLogLevelRequest::MergeFrom(const GetLogLevelRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetLogLevelRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  entities_.MergeFrom(from.entities_);
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+}
+
+void GetLogLevelRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetLogLevelRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GetLogLevelRequest::CopyFrom(const GetLogLevelRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.GetLogLevelRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetLogLevelRequest::IsInitialized() const {
+  return true;
+}
+
+void GetLogLevelRequest::Swap(GetLogLevelRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void GetLogLevelRequest::InternalSwap(GetLogLevelRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  entities_.InternalSwap(CastToBase(&other->entities_));
+  swap(device_uuid_, other->device_uuid_);
+}
+
+::google::protobuf::Metadata GetLogLevelRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void GetLogLevelResponse::InitAsDefaultInstance() {
+  ::dmi::_GetLogLevelResponse_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class GetLogLevelResponse::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const GetLogLevelResponse* msg);
+};
+
+const ::dmi::Uuid&
+GetLogLevelResponse::HasBitSetters::device_uuid(const GetLogLevelResponse* msg) {
+  return *msg->device_uuid_;
+}
+void GetLogLevelResponse::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GetLogLevelResponse::kDeviceUuidFieldNumber;
+const int GetLogLevelResponse::kLogLevelsFieldNumber;
+const int GetLogLevelResponse::kStatusFieldNumber;
+const int GetLogLevelResponse::kReasonFieldNumber;
+const int GetLogLevelResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GetLogLevelResponse::GetLogLevelResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.GetLogLevelResponse)
+}
+GetLogLevelResponse::GetLogLevelResponse(const GetLogLevelResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr),
+      loglevels_(from.loglevels_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.GetLogLevelResponse)
+}
+
+void GetLogLevelResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_GetLogLevelResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&device_uuid_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&device_uuid_)) + sizeof(reason_));
+}
+
+GetLogLevelResponse::~GetLogLevelResponse() {
+  // @@protoc_insertion_point(destructor:dmi.GetLogLevelResponse)
+  SharedDtor();
+}
+
+void GetLogLevelResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete device_uuid_;
+}
+
+void GetLogLevelResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const GetLogLevelResponse& GetLogLevelResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_GetLogLevelResponse_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void GetLogLevelResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.GetLogLevelResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  loglevels_.Clear();
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* GetLogLevelResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<GetLogLevelResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // repeated .dmi.EntitiesLogLevel logLevels = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        do {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          parser_till_end = ::dmi::EntitiesLogLevel::_InternalParse;
+          object = msg->add_loglevels();
+          if (size > end - ptr) goto len_delim_till_end;
+          ptr += size;
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+              {parser_till_end, object}, ptr - size, ptr));
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 18 && (ptr += 1));
+        break;
+      }
+      // .dmi.Status status = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.GetLogLevelResponse.Reason reason = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 32) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::GetLogLevelResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string reason_detail = 5;
+      case 5: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.GetLogLevelResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool GetLogLevelResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.GetLogLevelResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // repeated .dmi.EntitiesLogLevel logLevels = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+                input, add_loglevels()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Status status = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.GetLogLevelResponse.Reason reason = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (32 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::GetLogLevelResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 5;
+      case 5: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (42 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.GetLogLevelResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.GetLogLevelResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.GetLogLevelResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void GetLogLevelResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.GetLogLevelResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // repeated .dmi.EntitiesLogLevel logLevels = 2;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->loglevels_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2,
+      this->loglevels(static_cast<int>(i)),
+      output);
+  }
+
+  // .dmi.Status status = 3;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      3, this->status(), output);
+  }
+
+  // .dmi.GetLogLevelResponse.Reason reason = 4;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      4, this->reason(), output);
+  }
+
+  // string reason_detail = 5;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetLogLevelResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      5, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.GetLogLevelResponse)
+}
+
+::google::protobuf::uint8* GetLogLevelResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetLogLevelResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // repeated .dmi.EntitiesLogLevel logLevels = 2;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->loglevels_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, this->loglevels(static_cast<int>(i)), target);
+  }
+
+  // .dmi.Status status = 3;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      3, this->status(), target);
+  }
+
+  // .dmi.GetLogLevelResponse.Reason reason = 4;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      4, this->reason(), target);
+  }
+
+  // string reason_detail = 5;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetLogLevelResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        5, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetLogLevelResponse)
+  return target;
+}
+
+size_t GetLogLevelResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.GetLogLevelResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated .dmi.EntitiesLogLevel logLevels = 2;
+  {
+    unsigned int count = static_cast<unsigned int>(this->loglevels_size());
+    total_size += 1UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->loglevels(static_cast<int>(i)));
+    }
+  }
+
+  // string reason_detail = 5;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  // .dmi.Status status = 3;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.GetLogLevelResponse.Reason reason = 4;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void GetLogLevelResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetLogLevelResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const GetLogLevelResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<GetLogLevelResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetLogLevelResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetLogLevelResponse)
+    MergeFrom(*source);
+  }
+}
+
+void GetLogLevelResponse::MergeFrom(const GetLogLevelResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetLogLevelResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  loglevels_.MergeFrom(from.loglevels_);
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void GetLogLevelResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetLogLevelResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GetLogLevelResponse::CopyFrom(const GetLogLevelResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.GetLogLevelResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetLogLevelResponse::IsInitialized() const {
+  return true;
+}
+
+void GetLogLevelResponse::Swap(GetLogLevelResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void GetLogLevelResponse::InternalSwap(GetLogLevelResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  CastToBase(&loglevels_)->InternalSwap(CastToBase(&other->loglevels_));
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(device_uuid_, other->device_uuid_);
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata GetLogLevelResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void GetLoggableEntitiesRequest::InitAsDefaultInstance() {
+  ::dmi::_GetLoggableEntitiesRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class GetLoggableEntitiesRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const GetLoggableEntitiesRequest* msg);
+};
+
+const ::dmi::Uuid&
+GetLoggableEntitiesRequest::HasBitSetters::device_uuid(const GetLoggableEntitiesRequest* msg) {
+  return *msg->device_uuid_;
+}
+void GetLoggableEntitiesRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GetLoggableEntitiesRequest::kDeviceUuidFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GetLoggableEntitiesRequest::GetLoggableEntitiesRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.GetLoggableEntitiesRequest)
+}
+GetLoggableEntitiesRequest::GetLoggableEntitiesRequest(const GetLoggableEntitiesRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.GetLoggableEntitiesRequest)
+}
+
+void GetLoggableEntitiesRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_GetLoggableEntitiesRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  device_uuid_ = nullptr;
+}
+
+GetLoggableEntitiesRequest::~GetLoggableEntitiesRequest() {
+  // @@protoc_insertion_point(destructor:dmi.GetLoggableEntitiesRequest)
+  SharedDtor();
+}
+
+void GetLoggableEntitiesRequest::SharedDtor() {
+  if (this != internal_default_instance()) delete device_uuid_;
+}
+
+void GetLoggableEntitiesRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const GetLoggableEntitiesRequest& GetLoggableEntitiesRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_GetLoggableEntitiesRequest_dmi_2fhw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void GetLoggableEntitiesRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.GetLoggableEntitiesRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* GetLoggableEntitiesRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<GetLoggableEntitiesRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool GetLoggableEntitiesRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.GetLoggableEntitiesRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.GetLoggableEntitiesRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.GetLoggableEntitiesRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void GetLoggableEntitiesRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.GetLoggableEntitiesRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.GetLoggableEntitiesRequest)
+}
+
+::google::protobuf::uint8* GetLoggableEntitiesRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetLoggableEntitiesRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetLoggableEntitiesRequest)
+  return target;
+}
+
+size_t GetLoggableEntitiesRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.GetLoggableEntitiesRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void GetLoggableEntitiesRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetLoggableEntitiesRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const GetLoggableEntitiesRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<GetLoggableEntitiesRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetLoggableEntitiesRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetLoggableEntitiesRequest)
+    MergeFrom(*source);
+  }
+}
+
+void GetLoggableEntitiesRequest::MergeFrom(const GetLoggableEntitiesRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetLoggableEntitiesRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+}
+
+void GetLoggableEntitiesRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetLoggableEntitiesRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GetLoggableEntitiesRequest::CopyFrom(const GetLoggableEntitiesRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.GetLoggableEntitiesRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetLoggableEntitiesRequest::IsInitialized() const {
+  return true;
+}
+
+void GetLoggableEntitiesRequest::Swap(GetLoggableEntitiesRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void GetLoggableEntitiesRequest::InternalSwap(GetLoggableEntitiesRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(device_uuid_, other->device_uuid_);
+}
+
+::google::protobuf::Metadata GetLoggableEntitiesRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> PROTOBUF_NOINLINE ::dmi::PhysicalInventoryRequest* Arena::CreateMaybeMessage< ::dmi::PhysicalInventoryRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::PhysicalInventoryRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::PhysicalInventoryResponse* Arena::CreateMaybeMessage< ::dmi::PhysicalInventoryResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::PhysicalInventoryResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::HWComponentInfoGetRequest* Arena::CreateMaybeMessage< ::dmi::HWComponentInfoGetRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::HWComponentInfoGetRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::HWComponentInfoGetResponse* Arena::CreateMaybeMessage< ::dmi::HWComponentInfoGetResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::HWComponentInfoGetResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::HWComponentInfoSetRequest* Arena::CreateMaybeMessage< ::dmi::HWComponentInfoSetRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::HWComponentInfoSetRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::HWComponentInfoSetResponse* Arena::CreateMaybeMessage< ::dmi::HWComponentInfoSetResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::HWComponentInfoSetResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::StartManagingDeviceResponse* Arena::CreateMaybeMessage< ::dmi::StartManagingDeviceResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::StartManagingDeviceResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::StopManagingDeviceRequest* Arena::CreateMaybeMessage< ::dmi::StopManagingDeviceRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::StopManagingDeviceRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::StopManagingDeviceResponse* Arena::CreateMaybeMessage< ::dmi::StopManagingDeviceResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::StopManagingDeviceResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ManagedDeviceInfo* Arena::CreateMaybeMessage< ::dmi::ManagedDeviceInfo >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ManagedDeviceInfo >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ManagedDevicesResponse* Arena::CreateMaybeMessage< ::dmi::ManagedDevicesResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ManagedDevicesResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::SetLoggingEndpointRequest* Arena::CreateMaybeMessage< ::dmi::SetLoggingEndpointRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::SetLoggingEndpointRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::SetRemoteEndpointResponse* Arena::CreateMaybeMessage< ::dmi::SetRemoteEndpointResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::SetRemoteEndpointResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::GetLoggingEndpointResponse* Arena::CreateMaybeMessage< ::dmi::GetLoggingEndpointResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::GetLoggingEndpointResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::SetMsgBusEndpointRequest* Arena::CreateMaybeMessage< ::dmi::SetMsgBusEndpointRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::SetMsgBusEndpointRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::GetMsgBusEndpointResponse* Arena::CreateMaybeMessage< ::dmi::GetMsgBusEndpointResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::GetMsgBusEndpointResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::EntitiesLogLevel* Arena::CreateMaybeMessage< ::dmi::EntitiesLogLevel >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::EntitiesLogLevel >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::SetLogLevelRequest* Arena::CreateMaybeMessage< ::dmi::SetLogLevelRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::SetLogLevelRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::SetLogLevelResponse* Arena::CreateMaybeMessage< ::dmi::SetLogLevelResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::SetLogLevelResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::GetLogLevelRequest* Arena::CreateMaybeMessage< ::dmi::GetLogLevelRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::GetLogLevelRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::GetLogLevelResponse* Arena::CreateMaybeMessage< ::dmi::GetLogLevelResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::GetLogLevelResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::GetLoggableEntitiesRequest* Arena::CreateMaybeMessage< ::dmi::GetLoggableEntitiesRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::GetLoggableEntitiesRequest >(arena);
+}
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+#include <google/protobuf/port_undef.inc>
diff --git a/cpp/dmi/hw_management_service.pb.h b/cpp/dmi/hw_management_service.pb.h
new file mode 100644
index 0000000..a304aa1
--- /dev/null
+++ b/cpp/dmi/hw_management_service.pb.h
@@ -0,0 +1,6289 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/hw_management_service.proto
+
+#ifndef PROTOBUF_INCLUDED_dmi_2fhw_5fmanagement_5fservice_2eproto
+#define PROTOBUF_INCLUDED_dmi_2fhw_5fmanagement_5fservice_2eproto
+
+#include <limits>
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+#if PROTOBUF_VERSION < 3007000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3007000 < PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/port_undef.inc>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/inlined_string_field.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+#include "dmi/commons.pb.h"
+#include "dmi/hw.pb.h"
+#include <google/protobuf/empty.pb.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+#define PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmanagement_5fservice_2eproto
+
+// Internal implementation detail -- do not use these members.
+struct TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto {
+  static const ::google::protobuf::internal::ParseTableField entries[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::AuxillaryParseTableField aux[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::ParseTable schema[22]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
+  static const ::google::protobuf::uint32 offsets[];
+};
+void AddDescriptors_dmi_2fhw_5fmanagement_5fservice_2eproto();
+namespace dmi {
+class EntitiesLogLevel;
+class EntitiesLogLevelDefaultTypeInternal;
+extern EntitiesLogLevelDefaultTypeInternal _EntitiesLogLevel_default_instance_;
+class GetLogLevelRequest;
+class GetLogLevelRequestDefaultTypeInternal;
+extern GetLogLevelRequestDefaultTypeInternal _GetLogLevelRequest_default_instance_;
+class GetLogLevelResponse;
+class GetLogLevelResponseDefaultTypeInternal;
+extern GetLogLevelResponseDefaultTypeInternal _GetLogLevelResponse_default_instance_;
+class GetLoggableEntitiesRequest;
+class GetLoggableEntitiesRequestDefaultTypeInternal;
+extern GetLoggableEntitiesRequestDefaultTypeInternal _GetLoggableEntitiesRequest_default_instance_;
+class GetLoggingEndpointResponse;
+class GetLoggingEndpointResponseDefaultTypeInternal;
+extern GetLoggingEndpointResponseDefaultTypeInternal _GetLoggingEndpointResponse_default_instance_;
+class GetMsgBusEndpointResponse;
+class GetMsgBusEndpointResponseDefaultTypeInternal;
+extern GetMsgBusEndpointResponseDefaultTypeInternal _GetMsgBusEndpointResponse_default_instance_;
+class HWComponentInfoGetRequest;
+class HWComponentInfoGetRequestDefaultTypeInternal;
+extern HWComponentInfoGetRequestDefaultTypeInternal _HWComponentInfoGetRequest_default_instance_;
+class HWComponentInfoGetResponse;
+class HWComponentInfoGetResponseDefaultTypeInternal;
+extern HWComponentInfoGetResponseDefaultTypeInternal _HWComponentInfoGetResponse_default_instance_;
+class HWComponentInfoSetRequest;
+class HWComponentInfoSetRequestDefaultTypeInternal;
+extern HWComponentInfoSetRequestDefaultTypeInternal _HWComponentInfoSetRequest_default_instance_;
+class HWComponentInfoSetResponse;
+class HWComponentInfoSetResponseDefaultTypeInternal;
+extern HWComponentInfoSetResponseDefaultTypeInternal _HWComponentInfoSetResponse_default_instance_;
+class ManagedDeviceInfo;
+class ManagedDeviceInfoDefaultTypeInternal;
+extern ManagedDeviceInfoDefaultTypeInternal _ManagedDeviceInfo_default_instance_;
+class ManagedDevicesResponse;
+class ManagedDevicesResponseDefaultTypeInternal;
+extern ManagedDevicesResponseDefaultTypeInternal _ManagedDevicesResponse_default_instance_;
+class PhysicalInventoryRequest;
+class PhysicalInventoryRequestDefaultTypeInternal;
+extern PhysicalInventoryRequestDefaultTypeInternal _PhysicalInventoryRequest_default_instance_;
+class PhysicalInventoryResponse;
+class PhysicalInventoryResponseDefaultTypeInternal;
+extern PhysicalInventoryResponseDefaultTypeInternal _PhysicalInventoryResponse_default_instance_;
+class SetLogLevelRequest;
+class SetLogLevelRequestDefaultTypeInternal;
+extern SetLogLevelRequestDefaultTypeInternal _SetLogLevelRequest_default_instance_;
+class SetLogLevelResponse;
+class SetLogLevelResponseDefaultTypeInternal;
+extern SetLogLevelResponseDefaultTypeInternal _SetLogLevelResponse_default_instance_;
+class SetLoggingEndpointRequest;
+class SetLoggingEndpointRequestDefaultTypeInternal;
+extern SetLoggingEndpointRequestDefaultTypeInternal _SetLoggingEndpointRequest_default_instance_;
+class SetMsgBusEndpointRequest;
+class SetMsgBusEndpointRequestDefaultTypeInternal;
+extern SetMsgBusEndpointRequestDefaultTypeInternal _SetMsgBusEndpointRequest_default_instance_;
+class SetRemoteEndpointResponse;
+class SetRemoteEndpointResponseDefaultTypeInternal;
+extern SetRemoteEndpointResponseDefaultTypeInternal _SetRemoteEndpointResponse_default_instance_;
+class StartManagingDeviceResponse;
+class StartManagingDeviceResponseDefaultTypeInternal;
+extern StartManagingDeviceResponseDefaultTypeInternal _StartManagingDeviceResponse_default_instance_;
+class StopManagingDeviceRequest;
+class StopManagingDeviceRequestDefaultTypeInternal;
+extern StopManagingDeviceRequestDefaultTypeInternal _StopManagingDeviceRequest_default_instance_;
+class StopManagingDeviceResponse;
+class StopManagingDeviceResponseDefaultTypeInternal;
+extern StopManagingDeviceResponseDefaultTypeInternal _StopManagingDeviceResponse_default_instance_;
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> ::dmi::EntitiesLogLevel* Arena::CreateMaybeMessage<::dmi::EntitiesLogLevel>(Arena*);
+template<> ::dmi::GetLogLevelRequest* Arena::CreateMaybeMessage<::dmi::GetLogLevelRequest>(Arena*);
+template<> ::dmi::GetLogLevelResponse* Arena::CreateMaybeMessage<::dmi::GetLogLevelResponse>(Arena*);
+template<> ::dmi::GetLoggableEntitiesRequest* Arena::CreateMaybeMessage<::dmi::GetLoggableEntitiesRequest>(Arena*);
+template<> ::dmi::GetLoggingEndpointResponse* Arena::CreateMaybeMessage<::dmi::GetLoggingEndpointResponse>(Arena*);
+template<> ::dmi::GetMsgBusEndpointResponse* Arena::CreateMaybeMessage<::dmi::GetMsgBusEndpointResponse>(Arena*);
+template<> ::dmi::HWComponentInfoGetRequest* Arena::CreateMaybeMessage<::dmi::HWComponentInfoGetRequest>(Arena*);
+template<> ::dmi::HWComponentInfoGetResponse* Arena::CreateMaybeMessage<::dmi::HWComponentInfoGetResponse>(Arena*);
+template<> ::dmi::HWComponentInfoSetRequest* Arena::CreateMaybeMessage<::dmi::HWComponentInfoSetRequest>(Arena*);
+template<> ::dmi::HWComponentInfoSetResponse* Arena::CreateMaybeMessage<::dmi::HWComponentInfoSetResponse>(Arena*);
+template<> ::dmi::ManagedDeviceInfo* Arena::CreateMaybeMessage<::dmi::ManagedDeviceInfo>(Arena*);
+template<> ::dmi::ManagedDevicesResponse* Arena::CreateMaybeMessage<::dmi::ManagedDevicesResponse>(Arena*);
+template<> ::dmi::PhysicalInventoryRequest* Arena::CreateMaybeMessage<::dmi::PhysicalInventoryRequest>(Arena*);
+template<> ::dmi::PhysicalInventoryResponse* Arena::CreateMaybeMessage<::dmi::PhysicalInventoryResponse>(Arena*);
+template<> ::dmi::SetLogLevelRequest* Arena::CreateMaybeMessage<::dmi::SetLogLevelRequest>(Arena*);
+template<> ::dmi::SetLogLevelResponse* Arena::CreateMaybeMessage<::dmi::SetLogLevelResponse>(Arena*);
+template<> ::dmi::SetLoggingEndpointRequest* Arena::CreateMaybeMessage<::dmi::SetLoggingEndpointRequest>(Arena*);
+template<> ::dmi::SetMsgBusEndpointRequest* Arena::CreateMaybeMessage<::dmi::SetMsgBusEndpointRequest>(Arena*);
+template<> ::dmi::SetRemoteEndpointResponse* Arena::CreateMaybeMessage<::dmi::SetRemoteEndpointResponse>(Arena*);
+template<> ::dmi::StartManagingDeviceResponse* Arena::CreateMaybeMessage<::dmi::StartManagingDeviceResponse>(Arena*);
+template<> ::dmi::StopManagingDeviceRequest* Arena::CreateMaybeMessage<::dmi::StopManagingDeviceRequest>(Arena*);
+template<> ::dmi::StopManagingDeviceResponse* Arena::CreateMaybeMessage<::dmi::StopManagingDeviceResponse>(Arena*);
+}  // namespace protobuf
+}  // namespace google
+namespace dmi {
+
+enum PhysicalInventoryResponse_Reason {
+  PhysicalInventoryResponse_Reason_UNDEFINED_REASON = 0,
+  PhysicalInventoryResponse_Reason_UNKNOWN_DEVICE = 1,
+  PhysicalInventoryResponse_Reason_INTERNAL_ERROR = 2,
+  PhysicalInventoryResponse_Reason_DEVICE_UNREACHABLE = 3,
+  PhysicalInventoryResponse_Reason_PhysicalInventoryResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  PhysicalInventoryResponse_Reason_PhysicalInventoryResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool PhysicalInventoryResponse_Reason_IsValid(int value);
+const PhysicalInventoryResponse_Reason PhysicalInventoryResponse_Reason_Reason_MIN = PhysicalInventoryResponse_Reason_UNDEFINED_REASON;
+const PhysicalInventoryResponse_Reason PhysicalInventoryResponse_Reason_Reason_MAX = PhysicalInventoryResponse_Reason_DEVICE_UNREACHABLE;
+const int PhysicalInventoryResponse_Reason_Reason_ARRAYSIZE = PhysicalInventoryResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* PhysicalInventoryResponse_Reason_descriptor();
+inline const ::std::string& PhysicalInventoryResponse_Reason_Name(PhysicalInventoryResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    PhysicalInventoryResponse_Reason_descriptor(), value);
+}
+inline bool PhysicalInventoryResponse_Reason_Parse(
+    const ::std::string& name, PhysicalInventoryResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<PhysicalInventoryResponse_Reason>(
+    PhysicalInventoryResponse_Reason_descriptor(), name, value);
+}
+enum HWComponentInfoGetResponse_Reason {
+  HWComponentInfoGetResponse_Reason_UNDEFINED_REASON = 0,
+  HWComponentInfoGetResponse_Reason_UNKNOWN_DEVICE = 1,
+  HWComponentInfoGetResponse_Reason_UNKNOWN_COMPONENT = 2,
+  HWComponentInfoGetResponse_Reason_INTERNAL_ERROR = 3,
+  HWComponentInfoGetResponse_Reason_DEVICE_UNREACHABLE = 4,
+  HWComponentInfoGetResponse_Reason_HWComponentInfoGetResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  HWComponentInfoGetResponse_Reason_HWComponentInfoGetResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool HWComponentInfoGetResponse_Reason_IsValid(int value);
+const HWComponentInfoGetResponse_Reason HWComponentInfoGetResponse_Reason_Reason_MIN = HWComponentInfoGetResponse_Reason_UNDEFINED_REASON;
+const HWComponentInfoGetResponse_Reason HWComponentInfoGetResponse_Reason_Reason_MAX = HWComponentInfoGetResponse_Reason_DEVICE_UNREACHABLE;
+const int HWComponentInfoGetResponse_Reason_Reason_ARRAYSIZE = HWComponentInfoGetResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* HWComponentInfoGetResponse_Reason_descriptor();
+inline const ::std::string& HWComponentInfoGetResponse_Reason_Name(HWComponentInfoGetResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    HWComponentInfoGetResponse_Reason_descriptor(), value);
+}
+inline bool HWComponentInfoGetResponse_Reason_Parse(
+    const ::std::string& name, HWComponentInfoGetResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<HWComponentInfoGetResponse_Reason>(
+    HWComponentInfoGetResponse_Reason_descriptor(), name, value);
+}
+enum HWComponentInfoSetResponse_Reason {
+  HWComponentInfoSetResponse_Reason_UNDEFINED_REASON = 0,
+  HWComponentInfoSetResponse_Reason_UNKNOWN_DEVICE = 1,
+  HWComponentInfoSetResponse_Reason_UNKNOWN_COMPONENT = 2,
+  HWComponentInfoSetResponse_Reason_INVALID_PARAMS = 3,
+  HWComponentInfoSetResponse_Reason_INTERNAL_ERROR = 4,
+  HWComponentInfoSetResponse_Reason_DEVICE_UNREACHABLE = 5,
+  HWComponentInfoSetResponse_Reason_HWComponentInfoSetResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  HWComponentInfoSetResponse_Reason_HWComponentInfoSetResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool HWComponentInfoSetResponse_Reason_IsValid(int value);
+const HWComponentInfoSetResponse_Reason HWComponentInfoSetResponse_Reason_Reason_MIN = HWComponentInfoSetResponse_Reason_UNDEFINED_REASON;
+const HWComponentInfoSetResponse_Reason HWComponentInfoSetResponse_Reason_Reason_MAX = HWComponentInfoSetResponse_Reason_DEVICE_UNREACHABLE;
+const int HWComponentInfoSetResponse_Reason_Reason_ARRAYSIZE = HWComponentInfoSetResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* HWComponentInfoSetResponse_Reason_descriptor();
+inline const ::std::string& HWComponentInfoSetResponse_Reason_Name(HWComponentInfoSetResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    HWComponentInfoSetResponse_Reason_descriptor(), value);
+}
+inline bool HWComponentInfoSetResponse_Reason_Parse(
+    const ::std::string& name, HWComponentInfoSetResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<HWComponentInfoSetResponse_Reason>(
+    HWComponentInfoSetResponse_Reason_descriptor(), name, value);
+}
+enum StartManagingDeviceResponse_Reason {
+  StartManagingDeviceResponse_Reason_UNDEFINED_REASON = 0,
+  StartManagingDeviceResponse_Reason_DEVICE_ALREADY_MANAGED = 1,
+  StartManagingDeviceResponse_Reason_OPERATION_ALREADY_IN_PROGRESS = 2,
+  StartManagingDeviceResponse_Reason_INVALID_PARAMS = 3,
+  StartManagingDeviceResponse_Reason_INTERNAL_ERROR = 4,
+  StartManagingDeviceResponse_Reason_StartManagingDeviceResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  StartManagingDeviceResponse_Reason_StartManagingDeviceResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool StartManagingDeviceResponse_Reason_IsValid(int value);
+const StartManagingDeviceResponse_Reason StartManagingDeviceResponse_Reason_Reason_MIN = StartManagingDeviceResponse_Reason_UNDEFINED_REASON;
+const StartManagingDeviceResponse_Reason StartManagingDeviceResponse_Reason_Reason_MAX = StartManagingDeviceResponse_Reason_INTERNAL_ERROR;
+const int StartManagingDeviceResponse_Reason_Reason_ARRAYSIZE = StartManagingDeviceResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* StartManagingDeviceResponse_Reason_descriptor();
+inline const ::std::string& StartManagingDeviceResponse_Reason_Name(StartManagingDeviceResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    StartManagingDeviceResponse_Reason_descriptor(), value);
+}
+inline bool StartManagingDeviceResponse_Reason_Parse(
+    const ::std::string& name, StartManagingDeviceResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<StartManagingDeviceResponse_Reason>(
+    StartManagingDeviceResponse_Reason_descriptor(), name, value);
+}
+enum StopManagingDeviceResponse_Reason {
+  StopManagingDeviceResponse_Reason_UNDEFINED_REASON = 0,
+  StopManagingDeviceResponse_Reason_UNKNOWN_DEVICE = 1,
+  StopManagingDeviceResponse_Reason_StopManagingDeviceResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  StopManagingDeviceResponse_Reason_StopManagingDeviceResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool StopManagingDeviceResponse_Reason_IsValid(int value);
+const StopManagingDeviceResponse_Reason StopManagingDeviceResponse_Reason_Reason_MIN = StopManagingDeviceResponse_Reason_UNDEFINED_REASON;
+const StopManagingDeviceResponse_Reason StopManagingDeviceResponse_Reason_Reason_MAX = StopManagingDeviceResponse_Reason_UNKNOWN_DEVICE;
+const int StopManagingDeviceResponse_Reason_Reason_ARRAYSIZE = StopManagingDeviceResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* StopManagingDeviceResponse_Reason_descriptor();
+inline const ::std::string& StopManagingDeviceResponse_Reason_Name(StopManagingDeviceResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    StopManagingDeviceResponse_Reason_descriptor(), value);
+}
+inline bool StopManagingDeviceResponse_Reason_Parse(
+    const ::std::string& name, StopManagingDeviceResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<StopManagingDeviceResponse_Reason>(
+    StopManagingDeviceResponse_Reason_descriptor(), name, value);
+}
+enum ManagedDevicesResponse_Reason {
+  ManagedDevicesResponse_Reason_UNDEFINED_REASON = 0,
+  ManagedDevicesResponse_Reason_INTERNAL_ERROR = 1,
+  ManagedDevicesResponse_Reason_ManagedDevicesResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ManagedDevicesResponse_Reason_ManagedDevicesResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ManagedDevicesResponse_Reason_IsValid(int value);
+const ManagedDevicesResponse_Reason ManagedDevicesResponse_Reason_Reason_MIN = ManagedDevicesResponse_Reason_UNDEFINED_REASON;
+const ManagedDevicesResponse_Reason ManagedDevicesResponse_Reason_Reason_MAX = ManagedDevicesResponse_Reason_INTERNAL_ERROR;
+const int ManagedDevicesResponse_Reason_Reason_ARRAYSIZE = ManagedDevicesResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ManagedDevicesResponse_Reason_descriptor();
+inline const ::std::string& ManagedDevicesResponse_Reason_Name(ManagedDevicesResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ManagedDevicesResponse_Reason_descriptor(), value);
+}
+inline bool ManagedDevicesResponse_Reason_Parse(
+    const ::std::string& name, ManagedDevicesResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ManagedDevicesResponse_Reason>(
+    ManagedDevicesResponse_Reason_descriptor(), name, value);
+}
+enum SetRemoteEndpointResponse_Reason {
+  SetRemoteEndpointResponse_Reason_UNDEFINED_REASON = 0,
+  SetRemoteEndpointResponse_Reason_UNKNOWN_DEVICE = 1,
+  SetRemoteEndpointResponse_Reason_INTERNAL_ERROR = 2,
+  SetRemoteEndpointResponse_Reason_LOGGING_ENDPOINT_ERROR = 3,
+  SetRemoteEndpointResponse_Reason_LOGGING_ENDPOINT_PROTOCOL_ERROR = 4,
+  SetRemoteEndpointResponse_Reason_MSGBUS_ENDPOINT_ERROR = 5,
+  SetRemoteEndpointResponse_Reason_DEVICE_UNREACHABLE = 6,
+  SetRemoteEndpointResponse_Reason_SetRemoteEndpointResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  SetRemoteEndpointResponse_Reason_SetRemoteEndpointResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool SetRemoteEndpointResponse_Reason_IsValid(int value);
+const SetRemoteEndpointResponse_Reason SetRemoteEndpointResponse_Reason_Reason_MIN = SetRemoteEndpointResponse_Reason_UNDEFINED_REASON;
+const SetRemoteEndpointResponse_Reason SetRemoteEndpointResponse_Reason_Reason_MAX = SetRemoteEndpointResponse_Reason_DEVICE_UNREACHABLE;
+const int SetRemoteEndpointResponse_Reason_Reason_ARRAYSIZE = SetRemoteEndpointResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* SetRemoteEndpointResponse_Reason_descriptor();
+inline const ::std::string& SetRemoteEndpointResponse_Reason_Name(SetRemoteEndpointResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    SetRemoteEndpointResponse_Reason_descriptor(), value);
+}
+inline bool SetRemoteEndpointResponse_Reason_Parse(
+    const ::std::string& name, SetRemoteEndpointResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<SetRemoteEndpointResponse_Reason>(
+    SetRemoteEndpointResponse_Reason_descriptor(), name, value);
+}
+enum GetLoggingEndpointResponse_Reason {
+  GetLoggingEndpointResponse_Reason_UNDEFINED_REASON = 0,
+  GetLoggingEndpointResponse_Reason_UNKNOWN_DEVICE = 1,
+  GetLoggingEndpointResponse_Reason_INTERNAL_ERROR = 2,
+  GetLoggingEndpointResponse_Reason_DEVICE_UNREACHABLE = 3,
+  GetLoggingEndpointResponse_Reason_GetLoggingEndpointResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  GetLoggingEndpointResponse_Reason_GetLoggingEndpointResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool GetLoggingEndpointResponse_Reason_IsValid(int value);
+const GetLoggingEndpointResponse_Reason GetLoggingEndpointResponse_Reason_Reason_MIN = GetLoggingEndpointResponse_Reason_UNDEFINED_REASON;
+const GetLoggingEndpointResponse_Reason GetLoggingEndpointResponse_Reason_Reason_MAX = GetLoggingEndpointResponse_Reason_DEVICE_UNREACHABLE;
+const int GetLoggingEndpointResponse_Reason_Reason_ARRAYSIZE = GetLoggingEndpointResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* GetLoggingEndpointResponse_Reason_descriptor();
+inline const ::std::string& GetLoggingEndpointResponse_Reason_Name(GetLoggingEndpointResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    GetLoggingEndpointResponse_Reason_descriptor(), value);
+}
+inline bool GetLoggingEndpointResponse_Reason_Parse(
+    const ::std::string& name, GetLoggingEndpointResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<GetLoggingEndpointResponse_Reason>(
+    GetLoggingEndpointResponse_Reason_descriptor(), name, value);
+}
+enum GetMsgBusEndpointResponse_Reason {
+  GetMsgBusEndpointResponse_Reason_UNDEFINED_REASON = 0,
+  GetMsgBusEndpointResponse_Reason_INTERNAL_ERROR = 1,
+  GetMsgBusEndpointResponse_Reason_DEVICE_UNREACHABLE = 2,
+  GetMsgBusEndpointResponse_Reason_GetMsgBusEndpointResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  GetMsgBusEndpointResponse_Reason_GetMsgBusEndpointResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool GetMsgBusEndpointResponse_Reason_IsValid(int value);
+const GetMsgBusEndpointResponse_Reason GetMsgBusEndpointResponse_Reason_Reason_MIN = GetMsgBusEndpointResponse_Reason_UNDEFINED_REASON;
+const GetMsgBusEndpointResponse_Reason GetMsgBusEndpointResponse_Reason_Reason_MAX = GetMsgBusEndpointResponse_Reason_DEVICE_UNREACHABLE;
+const int GetMsgBusEndpointResponse_Reason_Reason_ARRAYSIZE = GetMsgBusEndpointResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* GetMsgBusEndpointResponse_Reason_descriptor();
+inline const ::std::string& GetMsgBusEndpointResponse_Reason_Name(GetMsgBusEndpointResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    GetMsgBusEndpointResponse_Reason_descriptor(), value);
+}
+inline bool GetMsgBusEndpointResponse_Reason_Parse(
+    const ::std::string& name, GetMsgBusEndpointResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<GetMsgBusEndpointResponse_Reason>(
+    GetMsgBusEndpointResponse_Reason_descriptor(), name, value);
+}
+enum SetLogLevelResponse_Reason {
+  SetLogLevelResponse_Reason_UNDEFINED_REASON = 0,
+  SetLogLevelResponse_Reason_UNKNOWN_DEVICE = 1,
+  SetLogLevelResponse_Reason_INTERNAL_ERROR = 2,
+  SetLogLevelResponse_Reason_UNKNOWN_LOG_ENTITY = 3,
+  SetLogLevelResponse_Reason_DEVICE_UNREACHABLE = 4,
+  SetLogLevelResponse_Reason_SetLogLevelResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  SetLogLevelResponse_Reason_SetLogLevelResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool SetLogLevelResponse_Reason_IsValid(int value);
+const SetLogLevelResponse_Reason SetLogLevelResponse_Reason_Reason_MIN = SetLogLevelResponse_Reason_UNDEFINED_REASON;
+const SetLogLevelResponse_Reason SetLogLevelResponse_Reason_Reason_MAX = SetLogLevelResponse_Reason_DEVICE_UNREACHABLE;
+const int SetLogLevelResponse_Reason_Reason_ARRAYSIZE = SetLogLevelResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* SetLogLevelResponse_Reason_descriptor();
+inline const ::std::string& SetLogLevelResponse_Reason_Name(SetLogLevelResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    SetLogLevelResponse_Reason_descriptor(), value);
+}
+inline bool SetLogLevelResponse_Reason_Parse(
+    const ::std::string& name, SetLogLevelResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<SetLogLevelResponse_Reason>(
+    SetLogLevelResponse_Reason_descriptor(), name, value);
+}
+enum GetLogLevelResponse_Reason {
+  GetLogLevelResponse_Reason_UNDEFINED_REASON = 0,
+  GetLogLevelResponse_Reason_UNKNOWN_DEVICE = 1,
+  GetLogLevelResponse_Reason_INTERNAL_ERROR = 2,
+  GetLogLevelResponse_Reason_UNKNOWN_LOG_ENTITY = 3,
+  GetLogLevelResponse_Reason_DEVICE_UNREACHABLE = 4,
+  GetLogLevelResponse_Reason_GetLogLevelResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  GetLogLevelResponse_Reason_GetLogLevelResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool GetLogLevelResponse_Reason_IsValid(int value);
+const GetLogLevelResponse_Reason GetLogLevelResponse_Reason_Reason_MIN = GetLogLevelResponse_Reason_UNDEFINED_REASON;
+const GetLogLevelResponse_Reason GetLogLevelResponse_Reason_Reason_MAX = GetLogLevelResponse_Reason_DEVICE_UNREACHABLE;
+const int GetLogLevelResponse_Reason_Reason_ARRAYSIZE = GetLogLevelResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* GetLogLevelResponse_Reason_descriptor();
+inline const ::std::string& GetLogLevelResponse_Reason_Name(GetLogLevelResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    GetLogLevelResponse_Reason_descriptor(), value);
+}
+inline bool GetLogLevelResponse_Reason_Parse(
+    const ::std::string& name, GetLogLevelResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<GetLogLevelResponse_Reason>(
+    GetLogLevelResponse_Reason_descriptor(), name, value);
+}
+// ===================================================================
+
+class PhysicalInventoryRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.PhysicalInventoryRequest) */ {
+ public:
+  PhysicalInventoryRequest();
+  virtual ~PhysicalInventoryRequest();
+
+  PhysicalInventoryRequest(const PhysicalInventoryRequest& from);
+
+  inline PhysicalInventoryRequest& operator=(const PhysicalInventoryRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  PhysicalInventoryRequest(PhysicalInventoryRequest&& from) noexcept
+    : PhysicalInventoryRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline PhysicalInventoryRequest& operator=(PhysicalInventoryRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const PhysicalInventoryRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const PhysicalInventoryRequest* internal_default_instance() {
+    return reinterpret_cast<const PhysicalInventoryRequest*>(
+               &_PhysicalInventoryRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    0;
+
+  void Swap(PhysicalInventoryRequest* other);
+  friend void swap(PhysicalInventoryRequest& a, PhysicalInventoryRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline PhysicalInventoryRequest* New() const final {
+    return CreateMaybeMessage<PhysicalInventoryRequest>(nullptr);
+  }
+
+  PhysicalInventoryRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<PhysicalInventoryRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const PhysicalInventoryRequest& from);
+  void MergeFrom(const PhysicalInventoryRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(PhysicalInventoryRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.PhysicalInventoryRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::Uuid* device_uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class PhysicalInventoryResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.PhysicalInventoryResponse) */ {
+ public:
+  PhysicalInventoryResponse();
+  virtual ~PhysicalInventoryResponse();
+
+  PhysicalInventoryResponse(const PhysicalInventoryResponse& from);
+
+  inline PhysicalInventoryResponse& operator=(const PhysicalInventoryResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  PhysicalInventoryResponse(PhysicalInventoryResponse&& from) noexcept
+    : PhysicalInventoryResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline PhysicalInventoryResponse& operator=(PhysicalInventoryResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const PhysicalInventoryResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const PhysicalInventoryResponse* internal_default_instance() {
+    return reinterpret_cast<const PhysicalInventoryResponse*>(
+               &_PhysicalInventoryResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    1;
+
+  void Swap(PhysicalInventoryResponse* other);
+  friend void swap(PhysicalInventoryResponse& a, PhysicalInventoryResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline PhysicalInventoryResponse* New() const final {
+    return CreateMaybeMessage<PhysicalInventoryResponse>(nullptr);
+  }
+
+  PhysicalInventoryResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<PhysicalInventoryResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const PhysicalInventoryResponse& from);
+  void MergeFrom(const PhysicalInventoryResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(PhysicalInventoryResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef PhysicalInventoryResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    PhysicalInventoryResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    PhysicalInventoryResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    PhysicalInventoryResponse_Reason_INTERNAL_ERROR;
+  static const Reason DEVICE_UNREACHABLE =
+    PhysicalInventoryResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return PhysicalInventoryResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    PhysicalInventoryResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    PhysicalInventoryResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    PhysicalInventoryResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return PhysicalInventoryResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return PhysicalInventoryResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return PhysicalInventoryResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 4;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 4;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Hardware inventory = 3;
+  bool has_inventory() const;
+  void clear_inventory();
+  static const int kInventoryFieldNumber = 3;
+  const ::dmi::Hardware& inventory() const;
+  ::dmi::Hardware* release_inventory();
+  ::dmi::Hardware* mutable_inventory();
+  void set_allocated_inventory(::dmi::Hardware* inventory);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.PhysicalInventoryResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::PhysicalInventoryResponse_Reason reason() const;
+  void set_reason(::dmi::PhysicalInventoryResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.PhysicalInventoryResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  ::dmi::Hardware* inventory_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class HWComponentInfoGetRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.HWComponentInfoGetRequest) */ {
+ public:
+  HWComponentInfoGetRequest();
+  virtual ~HWComponentInfoGetRequest();
+
+  HWComponentInfoGetRequest(const HWComponentInfoGetRequest& from);
+
+  inline HWComponentInfoGetRequest& operator=(const HWComponentInfoGetRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  HWComponentInfoGetRequest(HWComponentInfoGetRequest&& from) noexcept
+    : HWComponentInfoGetRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline HWComponentInfoGetRequest& operator=(HWComponentInfoGetRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const HWComponentInfoGetRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const HWComponentInfoGetRequest* internal_default_instance() {
+    return reinterpret_cast<const HWComponentInfoGetRequest*>(
+               &_HWComponentInfoGetRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    2;
+
+  void Swap(HWComponentInfoGetRequest* other);
+  friend void swap(HWComponentInfoGetRequest& a, HWComponentInfoGetRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline HWComponentInfoGetRequest* New() const final {
+    return CreateMaybeMessage<HWComponentInfoGetRequest>(nullptr);
+  }
+
+  HWComponentInfoGetRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<HWComponentInfoGetRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const HWComponentInfoGetRequest& from);
+  void MergeFrom(const HWComponentInfoGetRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(HWComponentInfoGetRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string component_name = 3;
+  void clear_component_name();
+  static const int kComponentNameFieldNumber = 3;
+  const ::std::string& component_name() const;
+  void set_component_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_component_name(::std::string&& value);
+  #endif
+  void set_component_name(const char* value);
+  void set_component_name(const char* value, size_t size);
+  ::std::string* mutable_component_name();
+  ::std::string* release_component_name();
+  void set_allocated_component_name(::std::string* component_name);
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // .dmi.Uuid component_uuid = 2;
+  bool has_component_uuid() const;
+  void clear_component_uuid();
+  static const int kComponentUuidFieldNumber = 2;
+  const ::dmi::Uuid& component_uuid() const;
+  ::dmi::Uuid* release_component_uuid();
+  ::dmi::Uuid* mutable_component_uuid();
+  void set_allocated_component_uuid(::dmi::Uuid* component_uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.HWComponentInfoGetRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr component_name_;
+  ::dmi::Uuid* device_uuid_;
+  ::dmi::Uuid* component_uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class HWComponentInfoGetResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.HWComponentInfoGetResponse) */ {
+ public:
+  HWComponentInfoGetResponse();
+  virtual ~HWComponentInfoGetResponse();
+
+  HWComponentInfoGetResponse(const HWComponentInfoGetResponse& from);
+
+  inline HWComponentInfoGetResponse& operator=(const HWComponentInfoGetResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  HWComponentInfoGetResponse(HWComponentInfoGetResponse&& from) noexcept
+    : HWComponentInfoGetResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline HWComponentInfoGetResponse& operator=(HWComponentInfoGetResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const HWComponentInfoGetResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const HWComponentInfoGetResponse* internal_default_instance() {
+    return reinterpret_cast<const HWComponentInfoGetResponse*>(
+               &_HWComponentInfoGetResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    3;
+
+  void Swap(HWComponentInfoGetResponse* other);
+  friend void swap(HWComponentInfoGetResponse& a, HWComponentInfoGetResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline HWComponentInfoGetResponse* New() const final {
+    return CreateMaybeMessage<HWComponentInfoGetResponse>(nullptr);
+  }
+
+  HWComponentInfoGetResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<HWComponentInfoGetResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const HWComponentInfoGetResponse& from);
+  void MergeFrom(const HWComponentInfoGetResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(HWComponentInfoGetResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef HWComponentInfoGetResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    HWComponentInfoGetResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    HWComponentInfoGetResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason UNKNOWN_COMPONENT =
+    HWComponentInfoGetResponse_Reason_UNKNOWN_COMPONENT;
+  static const Reason INTERNAL_ERROR =
+    HWComponentInfoGetResponse_Reason_INTERNAL_ERROR;
+  static const Reason DEVICE_UNREACHABLE =
+    HWComponentInfoGetResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return HWComponentInfoGetResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    HWComponentInfoGetResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    HWComponentInfoGetResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    HWComponentInfoGetResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return HWComponentInfoGetResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return HWComponentInfoGetResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return HWComponentInfoGetResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 4;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 4;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Component component = 3;
+  bool has_component() const;
+  void clear_component();
+  static const int kComponentFieldNumber = 3;
+  const ::dmi::Component& component() const;
+  ::dmi::Component* release_component();
+  ::dmi::Component* mutable_component();
+  void set_allocated_component(::dmi::Component* component);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.HWComponentInfoGetResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::HWComponentInfoGetResponse_Reason reason() const;
+  void set_reason(::dmi::HWComponentInfoGetResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.HWComponentInfoGetResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  ::dmi::Component* component_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class HWComponentInfoSetRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.HWComponentInfoSetRequest) */ {
+ public:
+  HWComponentInfoSetRequest();
+  virtual ~HWComponentInfoSetRequest();
+
+  HWComponentInfoSetRequest(const HWComponentInfoSetRequest& from);
+
+  inline HWComponentInfoSetRequest& operator=(const HWComponentInfoSetRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  HWComponentInfoSetRequest(HWComponentInfoSetRequest&& from) noexcept
+    : HWComponentInfoSetRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline HWComponentInfoSetRequest& operator=(HWComponentInfoSetRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const HWComponentInfoSetRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const HWComponentInfoSetRequest* internal_default_instance() {
+    return reinterpret_cast<const HWComponentInfoSetRequest*>(
+               &_HWComponentInfoSetRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    4;
+
+  void Swap(HWComponentInfoSetRequest* other);
+  friend void swap(HWComponentInfoSetRequest& a, HWComponentInfoSetRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline HWComponentInfoSetRequest* New() const final {
+    return CreateMaybeMessage<HWComponentInfoSetRequest>(nullptr);
+  }
+
+  HWComponentInfoSetRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<HWComponentInfoSetRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const HWComponentInfoSetRequest& from);
+  void MergeFrom(const HWComponentInfoSetRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(HWComponentInfoSetRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string component_name = 3;
+  void clear_component_name();
+  static const int kComponentNameFieldNumber = 3;
+  const ::std::string& component_name() const;
+  void set_component_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_component_name(::std::string&& value);
+  #endif
+  void set_component_name(const char* value);
+  void set_component_name(const char* value, size_t size);
+  ::std::string* mutable_component_name();
+  ::std::string* release_component_name();
+  void set_allocated_component_name(::std::string* component_name);
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // .dmi.Uuid component_uuid = 2;
+  bool has_component_uuid() const;
+  void clear_component_uuid();
+  static const int kComponentUuidFieldNumber = 2;
+  const ::dmi::Uuid& component_uuid() const;
+  ::dmi::Uuid* release_component_uuid();
+  ::dmi::Uuid* mutable_component_uuid();
+  void set_allocated_component_uuid(::dmi::Uuid* component_uuid);
+
+  // .dmi.ModifiableComponent changes = 4;
+  bool has_changes() const;
+  void clear_changes();
+  static const int kChangesFieldNumber = 4;
+  const ::dmi::ModifiableComponent& changes() const;
+  ::dmi::ModifiableComponent* release_changes();
+  ::dmi::ModifiableComponent* mutable_changes();
+  void set_allocated_changes(::dmi::ModifiableComponent* changes);
+
+  // @@protoc_insertion_point(class_scope:dmi.HWComponentInfoSetRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr component_name_;
+  ::dmi::Uuid* device_uuid_;
+  ::dmi::Uuid* component_uuid_;
+  ::dmi::ModifiableComponent* changes_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class HWComponentInfoSetResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.HWComponentInfoSetResponse) */ {
+ public:
+  HWComponentInfoSetResponse();
+  virtual ~HWComponentInfoSetResponse();
+
+  HWComponentInfoSetResponse(const HWComponentInfoSetResponse& from);
+
+  inline HWComponentInfoSetResponse& operator=(const HWComponentInfoSetResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  HWComponentInfoSetResponse(HWComponentInfoSetResponse&& from) noexcept
+    : HWComponentInfoSetResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline HWComponentInfoSetResponse& operator=(HWComponentInfoSetResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const HWComponentInfoSetResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const HWComponentInfoSetResponse* internal_default_instance() {
+    return reinterpret_cast<const HWComponentInfoSetResponse*>(
+               &_HWComponentInfoSetResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    5;
+
+  void Swap(HWComponentInfoSetResponse* other);
+  friend void swap(HWComponentInfoSetResponse& a, HWComponentInfoSetResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline HWComponentInfoSetResponse* New() const final {
+    return CreateMaybeMessage<HWComponentInfoSetResponse>(nullptr);
+  }
+
+  HWComponentInfoSetResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<HWComponentInfoSetResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const HWComponentInfoSetResponse& from);
+  void MergeFrom(const HWComponentInfoSetResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(HWComponentInfoSetResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef HWComponentInfoSetResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    HWComponentInfoSetResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    HWComponentInfoSetResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason UNKNOWN_COMPONENT =
+    HWComponentInfoSetResponse_Reason_UNKNOWN_COMPONENT;
+  static const Reason INVALID_PARAMS =
+    HWComponentInfoSetResponse_Reason_INVALID_PARAMS;
+  static const Reason INTERNAL_ERROR =
+    HWComponentInfoSetResponse_Reason_INTERNAL_ERROR;
+  static const Reason DEVICE_UNREACHABLE =
+    HWComponentInfoSetResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return HWComponentInfoSetResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    HWComponentInfoSetResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    HWComponentInfoSetResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    HWComponentInfoSetResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return HWComponentInfoSetResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return HWComponentInfoSetResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return HWComponentInfoSetResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 3;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 3;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.HWComponentInfoSetResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::HWComponentInfoSetResponse_Reason reason() const;
+  void set_reason(::dmi::HWComponentInfoSetResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.HWComponentInfoSetResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class StartManagingDeviceResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.StartManagingDeviceResponse) */ {
+ public:
+  StartManagingDeviceResponse();
+  virtual ~StartManagingDeviceResponse();
+
+  StartManagingDeviceResponse(const StartManagingDeviceResponse& from);
+
+  inline StartManagingDeviceResponse& operator=(const StartManagingDeviceResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  StartManagingDeviceResponse(StartManagingDeviceResponse&& from) noexcept
+    : StartManagingDeviceResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline StartManagingDeviceResponse& operator=(StartManagingDeviceResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const StartManagingDeviceResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const StartManagingDeviceResponse* internal_default_instance() {
+    return reinterpret_cast<const StartManagingDeviceResponse*>(
+               &_StartManagingDeviceResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    6;
+
+  void Swap(StartManagingDeviceResponse* other);
+  friend void swap(StartManagingDeviceResponse& a, StartManagingDeviceResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline StartManagingDeviceResponse* New() const final {
+    return CreateMaybeMessage<StartManagingDeviceResponse>(nullptr);
+  }
+
+  StartManagingDeviceResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<StartManagingDeviceResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const StartManagingDeviceResponse& from);
+  void MergeFrom(const StartManagingDeviceResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(StartManagingDeviceResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef StartManagingDeviceResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    StartManagingDeviceResponse_Reason_UNDEFINED_REASON;
+  static const Reason DEVICE_ALREADY_MANAGED =
+    StartManagingDeviceResponse_Reason_DEVICE_ALREADY_MANAGED;
+  static const Reason OPERATION_ALREADY_IN_PROGRESS =
+    StartManagingDeviceResponse_Reason_OPERATION_ALREADY_IN_PROGRESS;
+  static const Reason INVALID_PARAMS =
+    StartManagingDeviceResponse_Reason_INVALID_PARAMS;
+  static const Reason INTERNAL_ERROR =
+    StartManagingDeviceResponse_Reason_INTERNAL_ERROR;
+  static inline bool Reason_IsValid(int value) {
+    return StartManagingDeviceResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    StartManagingDeviceResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    StartManagingDeviceResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    StartManagingDeviceResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return StartManagingDeviceResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return StartManagingDeviceResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return StartManagingDeviceResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 4;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 4;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Uuid device_uuid = 3;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 3;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.StartManagingDeviceResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::StartManagingDeviceResponse_Reason reason() const;
+  void set_reason(::dmi::StartManagingDeviceResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.StartManagingDeviceResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  ::dmi::Uuid* device_uuid_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class StopManagingDeviceRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.StopManagingDeviceRequest) */ {
+ public:
+  StopManagingDeviceRequest();
+  virtual ~StopManagingDeviceRequest();
+
+  StopManagingDeviceRequest(const StopManagingDeviceRequest& from);
+
+  inline StopManagingDeviceRequest& operator=(const StopManagingDeviceRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  StopManagingDeviceRequest(StopManagingDeviceRequest&& from) noexcept
+    : StopManagingDeviceRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline StopManagingDeviceRequest& operator=(StopManagingDeviceRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const StopManagingDeviceRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const StopManagingDeviceRequest* internal_default_instance() {
+    return reinterpret_cast<const StopManagingDeviceRequest*>(
+               &_StopManagingDeviceRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    7;
+
+  void Swap(StopManagingDeviceRequest* other);
+  friend void swap(StopManagingDeviceRequest& a, StopManagingDeviceRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline StopManagingDeviceRequest* New() const final {
+    return CreateMaybeMessage<StopManagingDeviceRequest>(nullptr);
+  }
+
+  StopManagingDeviceRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<StopManagingDeviceRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const StopManagingDeviceRequest& from);
+  void MergeFrom(const StopManagingDeviceRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(StopManagingDeviceRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string name = 1;
+  void clear_name();
+  static const int kNameFieldNumber = 1;
+  const ::std::string& name() const;
+  void set_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_name(::std::string&& value);
+  #endif
+  void set_name(const char* value);
+  void set_name(const char* value, size_t size);
+  ::std::string* mutable_name();
+  ::std::string* release_name();
+  void set_allocated_name(::std::string* name);
+
+  // @@protoc_insertion_point(class_scope:dmi.StopManagingDeviceRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr name_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class StopManagingDeviceResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.StopManagingDeviceResponse) */ {
+ public:
+  StopManagingDeviceResponse();
+  virtual ~StopManagingDeviceResponse();
+
+  StopManagingDeviceResponse(const StopManagingDeviceResponse& from);
+
+  inline StopManagingDeviceResponse& operator=(const StopManagingDeviceResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  StopManagingDeviceResponse(StopManagingDeviceResponse&& from) noexcept
+    : StopManagingDeviceResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline StopManagingDeviceResponse& operator=(StopManagingDeviceResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const StopManagingDeviceResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const StopManagingDeviceResponse* internal_default_instance() {
+    return reinterpret_cast<const StopManagingDeviceResponse*>(
+               &_StopManagingDeviceResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    8;
+
+  void Swap(StopManagingDeviceResponse* other);
+  friend void swap(StopManagingDeviceResponse& a, StopManagingDeviceResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline StopManagingDeviceResponse* New() const final {
+    return CreateMaybeMessage<StopManagingDeviceResponse>(nullptr);
+  }
+
+  StopManagingDeviceResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<StopManagingDeviceResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const StopManagingDeviceResponse& from);
+  void MergeFrom(const StopManagingDeviceResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(StopManagingDeviceResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef StopManagingDeviceResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    StopManagingDeviceResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    StopManagingDeviceResponse_Reason_UNKNOWN_DEVICE;
+  static inline bool Reason_IsValid(int value) {
+    return StopManagingDeviceResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    StopManagingDeviceResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    StopManagingDeviceResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    StopManagingDeviceResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return StopManagingDeviceResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return StopManagingDeviceResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return StopManagingDeviceResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 3;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 3;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.StopManagingDeviceResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::StopManagingDeviceResponse_Reason reason() const;
+  void set_reason(::dmi::StopManagingDeviceResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.StopManagingDeviceResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ManagedDeviceInfo final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ManagedDeviceInfo) */ {
+ public:
+  ManagedDeviceInfo();
+  virtual ~ManagedDeviceInfo();
+
+  ManagedDeviceInfo(const ManagedDeviceInfo& from);
+
+  inline ManagedDeviceInfo& operator=(const ManagedDeviceInfo& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ManagedDeviceInfo(ManagedDeviceInfo&& from) noexcept
+    : ManagedDeviceInfo() {
+    *this = ::std::move(from);
+  }
+
+  inline ManagedDeviceInfo& operator=(ManagedDeviceInfo&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ManagedDeviceInfo& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ManagedDeviceInfo* internal_default_instance() {
+    return reinterpret_cast<const ManagedDeviceInfo*>(
+               &_ManagedDeviceInfo_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    9;
+
+  void Swap(ManagedDeviceInfo* other);
+  friend void swap(ManagedDeviceInfo& a, ManagedDeviceInfo& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ManagedDeviceInfo* New() const final {
+    return CreateMaybeMessage<ManagedDeviceInfo>(nullptr);
+  }
+
+  ManagedDeviceInfo* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ManagedDeviceInfo>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ManagedDeviceInfo& from);
+  void MergeFrom(const ManagedDeviceInfo& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ManagedDeviceInfo* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.ModifiableComponent info = 1;
+  bool has_info() const;
+  void clear_info();
+  static const int kInfoFieldNumber = 1;
+  const ::dmi::ModifiableComponent& info() const;
+  ::dmi::ModifiableComponent* release_info();
+  ::dmi::ModifiableComponent* mutable_info();
+  void set_allocated_info(::dmi::ModifiableComponent* info);
+
+  // .dmi.Uuid device_uuid = 2;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 2;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.ManagedDeviceInfo)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::ModifiableComponent* info_;
+  ::dmi::Uuid* device_uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ManagedDevicesResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ManagedDevicesResponse) */ {
+ public:
+  ManagedDevicesResponse();
+  virtual ~ManagedDevicesResponse();
+
+  ManagedDevicesResponse(const ManagedDevicesResponse& from);
+
+  inline ManagedDevicesResponse& operator=(const ManagedDevicesResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ManagedDevicesResponse(ManagedDevicesResponse&& from) noexcept
+    : ManagedDevicesResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline ManagedDevicesResponse& operator=(ManagedDevicesResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ManagedDevicesResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ManagedDevicesResponse* internal_default_instance() {
+    return reinterpret_cast<const ManagedDevicesResponse*>(
+               &_ManagedDevicesResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    10;
+
+  void Swap(ManagedDevicesResponse* other);
+  friend void swap(ManagedDevicesResponse& a, ManagedDevicesResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ManagedDevicesResponse* New() const final {
+    return CreateMaybeMessage<ManagedDevicesResponse>(nullptr);
+  }
+
+  ManagedDevicesResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ManagedDevicesResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ManagedDevicesResponse& from);
+  void MergeFrom(const ManagedDevicesResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ManagedDevicesResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef ManagedDevicesResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    ManagedDevicesResponse_Reason_UNDEFINED_REASON;
+  static const Reason INTERNAL_ERROR =
+    ManagedDevicesResponse_Reason_INTERNAL_ERROR;
+  static inline bool Reason_IsValid(int value) {
+    return ManagedDevicesResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    ManagedDevicesResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    ManagedDevicesResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    ManagedDevicesResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return ManagedDevicesResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return ManagedDevicesResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return ManagedDevicesResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // repeated .dmi.ManagedDeviceInfo devices = 3;
+  int devices_size() const;
+  void clear_devices();
+  static const int kDevicesFieldNumber = 3;
+  ::dmi::ManagedDeviceInfo* mutable_devices(int index);
+  ::google::protobuf::RepeatedPtrField< ::dmi::ManagedDeviceInfo >*
+      mutable_devices();
+  const ::dmi::ManagedDeviceInfo& devices(int index) const;
+  ::dmi::ManagedDeviceInfo* add_devices();
+  const ::google::protobuf::RepeatedPtrField< ::dmi::ManagedDeviceInfo >&
+      devices() const;
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.ManagedDevicesResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::ManagedDevicesResponse_Reason reason() const;
+  void set_reason(::dmi::ManagedDevicesResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.ManagedDevicesResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::RepeatedPtrField< ::dmi::ManagedDeviceInfo > devices_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class SetLoggingEndpointRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.SetLoggingEndpointRequest) */ {
+ public:
+  SetLoggingEndpointRequest();
+  virtual ~SetLoggingEndpointRequest();
+
+  SetLoggingEndpointRequest(const SetLoggingEndpointRequest& from);
+
+  inline SetLoggingEndpointRequest& operator=(const SetLoggingEndpointRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  SetLoggingEndpointRequest(SetLoggingEndpointRequest&& from) noexcept
+    : SetLoggingEndpointRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline SetLoggingEndpointRequest& operator=(SetLoggingEndpointRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const SetLoggingEndpointRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const SetLoggingEndpointRequest* internal_default_instance() {
+    return reinterpret_cast<const SetLoggingEndpointRequest*>(
+               &_SetLoggingEndpointRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    11;
+
+  void Swap(SetLoggingEndpointRequest* other);
+  friend void swap(SetLoggingEndpointRequest& a, SetLoggingEndpointRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline SetLoggingEndpointRequest* New() const final {
+    return CreateMaybeMessage<SetLoggingEndpointRequest>(nullptr);
+  }
+
+  SetLoggingEndpointRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<SetLoggingEndpointRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const SetLoggingEndpointRequest& from);
+  void MergeFrom(const SetLoggingEndpointRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(SetLoggingEndpointRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string logging_endpoint = 2;
+  void clear_logging_endpoint();
+  static const int kLoggingEndpointFieldNumber = 2;
+  const ::std::string& logging_endpoint() const;
+  void set_logging_endpoint(const ::std::string& value);
+  #if LANG_CXX11
+  void set_logging_endpoint(::std::string&& value);
+  #endif
+  void set_logging_endpoint(const char* value);
+  void set_logging_endpoint(const char* value, size_t size);
+  ::std::string* mutable_logging_endpoint();
+  ::std::string* release_logging_endpoint();
+  void set_allocated_logging_endpoint(::std::string* logging_endpoint);
+
+  // string logging_protocol = 3;
+  void clear_logging_protocol();
+  static const int kLoggingProtocolFieldNumber = 3;
+  const ::std::string& logging_protocol() const;
+  void set_logging_protocol(const ::std::string& value);
+  #if LANG_CXX11
+  void set_logging_protocol(::std::string&& value);
+  #endif
+  void set_logging_protocol(const char* value);
+  void set_logging_protocol(const char* value, size_t size);
+  ::std::string* mutable_logging_protocol();
+  ::std::string* release_logging_protocol();
+  void set_allocated_logging_protocol(::std::string* logging_protocol);
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.SetLoggingEndpointRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr logging_endpoint_;
+  ::google::protobuf::internal::ArenaStringPtr logging_protocol_;
+  ::dmi::Uuid* device_uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class SetRemoteEndpointResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.SetRemoteEndpointResponse) */ {
+ public:
+  SetRemoteEndpointResponse();
+  virtual ~SetRemoteEndpointResponse();
+
+  SetRemoteEndpointResponse(const SetRemoteEndpointResponse& from);
+
+  inline SetRemoteEndpointResponse& operator=(const SetRemoteEndpointResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  SetRemoteEndpointResponse(SetRemoteEndpointResponse&& from) noexcept
+    : SetRemoteEndpointResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline SetRemoteEndpointResponse& operator=(SetRemoteEndpointResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const SetRemoteEndpointResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const SetRemoteEndpointResponse* internal_default_instance() {
+    return reinterpret_cast<const SetRemoteEndpointResponse*>(
+               &_SetRemoteEndpointResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    12;
+
+  void Swap(SetRemoteEndpointResponse* other);
+  friend void swap(SetRemoteEndpointResponse& a, SetRemoteEndpointResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline SetRemoteEndpointResponse* New() const final {
+    return CreateMaybeMessage<SetRemoteEndpointResponse>(nullptr);
+  }
+
+  SetRemoteEndpointResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<SetRemoteEndpointResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const SetRemoteEndpointResponse& from);
+  void MergeFrom(const SetRemoteEndpointResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(SetRemoteEndpointResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef SetRemoteEndpointResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    SetRemoteEndpointResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    SetRemoteEndpointResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    SetRemoteEndpointResponse_Reason_INTERNAL_ERROR;
+  static const Reason LOGGING_ENDPOINT_ERROR =
+    SetRemoteEndpointResponse_Reason_LOGGING_ENDPOINT_ERROR;
+  static const Reason LOGGING_ENDPOINT_PROTOCOL_ERROR =
+    SetRemoteEndpointResponse_Reason_LOGGING_ENDPOINT_PROTOCOL_ERROR;
+  static const Reason MSGBUS_ENDPOINT_ERROR =
+    SetRemoteEndpointResponse_Reason_MSGBUS_ENDPOINT_ERROR;
+  static const Reason DEVICE_UNREACHABLE =
+    SetRemoteEndpointResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return SetRemoteEndpointResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    SetRemoteEndpointResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    SetRemoteEndpointResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    SetRemoteEndpointResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return SetRemoteEndpointResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return SetRemoteEndpointResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return SetRemoteEndpointResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 3;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 3;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.SetRemoteEndpointResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::SetRemoteEndpointResponse_Reason reason() const;
+  void set_reason(::dmi::SetRemoteEndpointResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.SetRemoteEndpointResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class GetLoggingEndpointResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.GetLoggingEndpointResponse) */ {
+ public:
+  GetLoggingEndpointResponse();
+  virtual ~GetLoggingEndpointResponse();
+
+  GetLoggingEndpointResponse(const GetLoggingEndpointResponse& from);
+
+  inline GetLoggingEndpointResponse& operator=(const GetLoggingEndpointResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  GetLoggingEndpointResponse(GetLoggingEndpointResponse&& from) noexcept
+    : GetLoggingEndpointResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline GetLoggingEndpointResponse& operator=(GetLoggingEndpointResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const GetLoggingEndpointResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const GetLoggingEndpointResponse* internal_default_instance() {
+    return reinterpret_cast<const GetLoggingEndpointResponse*>(
+               &_GetLoggingEndpointResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    13;
+
+  void Swap(GetLoggingEndpointResponse* other);
+  friend void swap(GetLoggingEndpointResponse& a, GetLoggingEndpointResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline GetLoggingEndpointResponse* New() const final {
+    return CreateMaybeMessage<GetLoggingEndpointResponse>(nullptr);
+  }
+
+  GetLoggingEndpointResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<GetLoggingEndpointResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const GetLoggingEndpointResponse& from);
+  void MergeFrom(const GetLoggingEndpointResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(GetLoggingEndpointResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef GetLoggingEndpointResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    GetLoggingEndpointResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    GetLoggingEndpointResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    GetLoggingEndpointResponse_Reason_INTERNAL_ERROR;
+  static const Reason DEVICE_UNREACHABLE =
+    GetLoggingEndpointResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return GetLoggingEndpointResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    GetLoggingEndpointResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    GetLoggingEndpointResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    GetLoggingEndpointResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return GetLoggingEndpointResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return GetLoggingEndpointResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return GetLoggingEndpointResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string logging_endpoint = 3;
+  void clear_logging_endpoint();
+  static const int kLoggingEndpointFieldNumber = 3;
+  const ::std::string& logging_endpoint() const;
+  void set_logging_endpoint(const ::std::string& value);
+  #if LANG_CXX11
+  void set_logging_endpoint(::std::string&& value);
+  #endif
+  void set_logging_endpoint(const char* value);
+  void set_logging_endpoint(const char* value, size_t size);
+  ::std::string* mutable_logging_endpoint();
+  ::std::string* release_logging_endpoint();
+  void set_allocated_logging_endpoint(::std::string* logging_endpoint);
+
+  // string logging_protocol = 4;
+  void clear_logging_protocol();
+  static const int kLoggingProtocolFieldNumber = 4;
+  const ::std::string& logging_protocol() const;
+  void set_logging_protocol(const ::std::string& value);
+  #if LANG_CXX11
+  void set_logging_protocol(::std::string&& value);
+  #endif
+  void set_logging_protocol(const char* value);
+  void set_logging_protocol(const char* value, size_t size);
+  ::std::string* mutable_logging_protocol();
+  ::std::string* release_logging_protocol();
+  void set_allocated_logging_protocol(::std::string* logging_protocol);
+
+  // string reason_detail = 5;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 5;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.GetLoggingEndpointResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::GetLoggingEndpointResponse_Reason reason() const;
+  void set_reason(::dmi::GetLoggingEndpointResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.GetLoggingEndpointResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr logging_endpoint_;
+  ::google::protobuf::internal::ArenaStringPtr logging_protocol_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class SetMsgBusEndpointRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.SetMsgBusEndpointRequest) */ {
+ public:
+  SetMsgBusEndpointRequest();
+  virtual ~SetMsgBusEndpointRequest();
+
+  SetMsgBusEndpointRequest(const SetMsgBusEndpointRequest& from);
+
+  inline SetMsgBusEndpointRequest& operator=(const SetMsgBusEndpointRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  SetMsgBusEndpointRequest(SetMsgBusEndpointRequest&& from) noexcept
+    : SetMsgBusEndpointRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline SetMsgBusEndpointRequest& operator=(SetMsgBusEndpointRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const SetMsgBusEndpointRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const SetMsgBusEndpointRequest* internal_default_instance() {
+    return reinterpret_cast<const SetMsgBusEndpointRequest*>(
+               &_SetMsgBusEndpointRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    14;
+
+  void Swap(SetMsgBusEndpointRequest* other);
+  friend void swap(SetMsgBusEndpointRequest& a, SetMsgBusEndpointRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline SetMsgBusEndpointRequest* New() const final {
+    return CreateMaybeMessage<SetMsgBusEndpointRequest>(nullptr);
+  }
+
+  SetMsgBusEndpointRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<SetMsgBusEndpointRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const SetMsgBusEndpointRequest& from);
+  void MergeFrom(const SetMsgBusEndpointRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(SetMsgBusEndpointRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string msgbus_endpoint = 1;
+  void clear_msgbus_endpoint();
+  static const int kMsgbusEndpointFieldNumber = 1;
+  const ::std::string& msgbus_endpoint() const;
+  void set_msgbus_endpoint(const ::std::string& value);
+  #if LANG_CXX11
+  void set_msgbus_endpoint(::std::string&& value);
+  #endif
+  void set_msgbus_endpoint(const char* value);
+  void set_msgbus_endpoint(const char* value, size_t size);
+  ::std::string* mutable_msgbus_endpoint();
+  ::std::string* release_msgbus_endpoint();
+  void set_allocated_msgbus_endpoint(::std::string* msgbus_endpoint);
+
+  // @@protoc_insertion_point(class_scope:dmi.SetMsgBusEndpointRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr msgbus_endpoint_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class GetMsgBusEndpointResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.GetMsgBusEndpointResponse) */ {
+ public:
+  GetMsgBusEndpointResponse();
+  virtual ~GetMsgBusEndpointResponse();
+
+  GetMsgBusEndpointResponse(const GetMsgBusEndpointResponse& from);
+
+  inline GetMsgBusEndpointResponse& operator=(const GetMsgBusEndpointResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  GetMsgBusEndpointResponse(GetMsgBusEndpointResponse&& from) noexcept
+    : GetMsgBusEndpointResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline GetMsgBusEndpointResponse& operator=(GetMsgBusEndpointResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const GetMsgBusEndpointResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const GetMsgBusEndpointResponse* internal_default_instance() {
+    return reinterpret_cast<const GetMsgBusEndpointResponse*>(
+               &_GetMsgBusEndpointResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    15;
+
+  void Swap(GetMsgBusEndpointResponse* other);
+  friend void swap(GetMsgBusEndpointResponse& a, GetMsgBusEndpointResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline GetMsgBusEndpointResponse* New() const final {
+    return CreateMaybeMessage<GetMsgBusEndpointResponse>(nullptr);
+  }
+
+  GetMsgBusEndpointResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<GetMsgBusEndpointResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const GetMsgBusEndpointResponse& from);
+  void MergeFrom(const GetMsgBusEndpointResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(GetMsgBusEndpointResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef GetMsgBusEndpointResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    GetMsgBusEndpointResponse_Reason_UNDEFINED_REASON;
+  static const Reason INTERNAL_ERROR =
+    GetMsgBusEndpointResponse_Reason_INTERNAL_ERROR;
+  static const Reason DEVICE_UNREACHABLE =
+    GetMsgBusEndpointResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return GetMsgBusEndpointResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    GetMsgBusEndpointResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    GetMsgBusEndpointResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    GetMsgBusEndpointResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return GetMsgBusEndpointResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return GetMsgBusEndpointResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return GetMsgBusEndpointResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string msgbus_endpoint = 3;
+  void clear_msgbus_endpoint();
+  static const int kMsgbusEndpointFieldNumber = 3;
+  const ::std::string& msgbus_endpoint() const;
+  void set_msgbus_endpoint(const ::std::string& value);
+  #if LANG_CXX11
+  void set_msgbus_endpoint(::std::string&& value);
+  #endif
+  void set_msgbus_endpoint(const char* value);
+  void set_msgbus_endpoint(const char* value, size_t size);
+  ::std::string* mutable_msgbus_endpoint();
+  ::std::string* release_msgbus_endpoint();
+  void set_allocated_msgbus_endpoint(::std::string* msgbus_endpoint);
+
+  // string reason_detail = 4;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 4;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.GetMsgBusEndpointResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::GetMsgBusEndpointResponse_Reason reason() const;
+  void set_reason(::dmi::GetMsgBusEndpointResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.GetMsgBusEndpointResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr msgbus_endpoint_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class EntitiesLogLevel final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EntitiesLogLevel) */ {
+ public:
+  EntitiesLogLevel();
+  virtual ~EntitiesLogLevel();
+
+  EntitiesLogLevel(const EntitiesLogLevel& from);
+
+  inline EntitiesLogLevel& operator=(const EntitiesLogLevel& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  EntitiesLogLevel(EntitiesLogLevel&& from) noexcept
+    : EntitiesLogLevel() {
+    *this = ::std::move(from);
+  }
+
+  inline EntitiesLogLevel& operator=(EntitiesLogLevel&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const EntitiesLogLevel& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const EntitiesLogLevel* internal_default_instance() {
+    return reinterpret_cast<const EntitiesLogLevel*>(
+               &_EntitiesLogLevel_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    16;
+
+  void Swap(EntitiesLogLevel* other);
+  friend void swap(EntitiesLogLevel& a, EntitiesLogLevel& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline EntitiesLogLevel* New() const final {
+    return CreateMaybeMessage<EntitiesLogLevel>(nullptr);
+  }
+
+  EntitiesLogLevel* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<EntitiesLogLevel>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const EntitiesLogLevel& from);
+  void MergeFrom(const EntitiesLogLevel& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(EntitiesLogLevel* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated string entities = 2;
+  int entities_size() const;
+  void clear_entities();
+  static const int kEntitiesFieldNumber = 2;
+  const ::std::string& entities(int index) const;
+  ::std::string* mutable_entities(int index);
+  void set_entities(int index, const ::std::string& value);
+  #if LANG_CXX11
+  void set_entities(int index, ::std::string&& value);
+  #endif
+  void set_entities(int index, const char* value);
+  void set_entities(int index, const char* value, size_t size);
+  ::std::string* add_entities();
+  void add_entities(const ::std::string& value);
+  #if LANG_CXX11
+  void add_entities(::std::string&& value);
+  #endif
+  void add_entities(const char* value);
+  void add_entities(const char* value, size_t size);
+  const ::google::protobuf::RepeatedPtrField<::std::string>& entities() const;
+  ::google::protobuf::RepeatedPtrField<::std::string>* mutable_entities();
+
+  // .dmi.LogLevel logLevel = 1;
+  void clear_loglevel();
+  static const int kLogLevelFieldNumber = 1;
+  ::dmi::LogLevel loglevel() const;
+  void set_loglevel(::dmi::LogLevel value);
+
+  // @@protoc_insertion_point(class_scope:dmi.EntitiesLogLevel)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::RepeatedPtrField<::std::string> entities_;
+  int loglevel_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class SetLogLevelRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.SetLogLevelRequest) */ {
+ public:
+  SetLogLevelRequest();
+  virtual ~SetLogLevelRequest();
+
+  SetLogLevelRequest(const SetLogLevelRequest& from);
+
+  inline SetLogLevelRequest& operator=(const SetLogLevelRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  SetLogLevelRequest(SetLogLevelRequest&& from) noexcept
+    : SetLogLevelRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline SetLogLevelRequest& operator=(SetLogLevelRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const SetLogLevelRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const SetLogLevelRequest* internal_default_instance() {
+    return reinterpret_cast<const SetLogLevelRequest*>(
+               &_SetLogLevelRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    17;
+
+  void Swap(SetLogLevelRequest* other);
+  friend void swap(SetLogLevelRequest& a, SetLogLevelRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline SetLogLevelRequest* New() const final {
+    return CreateMaybeMessage<SetLogLevelRequest>(nullptr);
+  }
+
+  SetLogLevelRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<SetLogLevelRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const SetLogLevelRequest& from);
+  void MergeFrom(const SetLogLevelRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(SetLogLevelRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated .dmi.EntitiesLogLevel loglevels = 2;
+  int loglevels_size() const;
+  void clear_loglevels();
+  static const int kLoglevelsFieldNumber = 2;
+  ::dmi::EntitiesLogLevel* mutable_loglevels(int index);
+  ::google::protobuf::RepeatedPtrField< ::dmi::EntitiesLogLevel >*
+      mutable_loglevels();
+  const ::dmi::EntitiesLogLevel& loglevels(int index) const;
+  ::dmi::EntitiesLogLevel* add_loglevels();
+  const ::google::protobuf::RepeatedPtrField< ::dmi::EntitiesLogLevel >&
+      loglevels() const;
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.SetLogLevelRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::RepeatedPtrField< ::dmi::EntitiesLogLevel > loglevels_;
+  ::dmi::Uuid* device_uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class SetLogLevelResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.SetLogLevelResponse) */ {
+ public:
+  SetLogLevelResponse();
+  virtual ~SetLogLevelResponse();
+
+  SetLogLevelResponse(const SetLogLevelResponse& from);
+
+  inline SetLogLevelResponse& operator=(const SetLogLevelResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  SetLogLevelResponse(SetLogLevelResponse&& from) noexcept
+    : SetLogLevelResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline SetLogLevelResponse& operator=(SetLogLevelResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const SetLogLevelResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const SetLogLevelResponse* internal_default_instance() {
+    return reinterpret_cast<const SetLogLevelResponse*>(
+               &_SetLogLevelResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    18;
+
+  void Swap(SetLogLevelResponse* other);
+  friend void swap(SetLogLevelResponse& a, SetLogLevelResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline SetLogLevelResponse* New() const final {
+    return CreateMaybeMessage<SetLogLevelResponse>(nullptr);
+  }
+
+  SetLogLevelResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<SetLogLevelResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const SetLogLevelResponse& from);
+  void MergeFrom(const SetLogLevelResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(SetLogLevelResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef SetLogLevelResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    SetLogLevelResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    SetLogLevelResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    SetLogLevelResponse_Reason_INTERNAL_ERROR;
+  static const Reason UNKNOWN_LOG_ENTITY =
+    SetLogLevelResponse_Reason_UNKNOWN_LOG_ENTITY;
+  static const Reason DEVICE_UNREACHABLE =
+    SetLogLevelResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return SetLogLevelResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    SetLogLevelResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    SetLogLevelResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    SetLogLevelResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return SetLogLevelResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return SetLogLevelResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return SetLogLevelResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 4;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 4;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // .dmi.Status status = 2;
+  void clear_status();
+  static const int kStatusFieldNumber = 2;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.SetLogLevelResponse.Reason reason = 3;
+  void clear_reason();
+  static const int kReasonFieldNumber = 3;
+  ::dmi::SetLogLevelResponse_Reason reason() const;
+  void set_reason(::dmi::SetLogLevelResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.SetLogLevelResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  ::dmi::Uuid* device_uuid_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class GetLogLevelRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.GetLogLevelRequest) */ {
+ public:
+  GetLogLevelRequest();
+  virtual ~GetLogLevelRequest();
+
+  GetLogLevelRequest(const GetLogLevelRequest& from);
+
+  inline GetLogLevelRequest& operator=(const GetLogLevelRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  GetLogLevelRequest(GetLogLevelRequest&& from) noexcept
+    : GetLogLevelRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline GetLogLevelRequest& operator=(GetLogLevelRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const GetLogLevelRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const GetLogLevelRequest* internal_default_instance() {
+    return reinterpret_cast<const GetLogLevelRequest*>(
+               &_GetLogLevelRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    19;
+
+  void Swap(GetLogLevelRequest* other);
+  friend void swap(GetLogLevelRequest& a, GetLogLevelRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline GetLogLevelRequest* New() const final {
+    return CreateMaybeMessage<GetLogLevelRequest>(nullptr);
+  }
+
+  GetLogLevelRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<GetLogLevelRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const GetLogLevelRequest& from);
+  void MergeFrom(const GetLogLevelRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(GetLogLevelRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated string entities = 2;
+  int entities_size() const;
+  void clear_entities();
+  static const int kEntitiesFieldNumber = 2;
+  const ::std::string& entities(int index) const;
+  ::std::string* mutable_entities(int index);
+  void set_entities(int index, const ::std::string& value);
+  #if LANG_CXX11
+  void set_entities(int index, ::std::string&& value);
+  #endif
+  void set_entities(int index, const char* value);
+  void set_entities(int index, const char* value, size_t size);
+  ::std::string* add_entities();
+  void add_entities(const ::std::string& value);
+  #if LANG_CXX11
+  void add_entities(::std::string&& value);
+  #endif
+  void add_entities(const char* value);
+  void add_entities(const char* value, size_t size);
+  const ::google::protobuf::RepeatedPtrField<::std::string>& entities() const;
+  ::google::protobuf::RepeatedPtrField<::std::string>* mutable_entities();
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.GetLogLevelRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::RepeatedPtrField<::std::string> entities_;
+  ::dmi::Uuid* device_uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class GetLogLevelResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.GetLogLevelResponse) */ {
+ public:
+  GetLogLevelResponse();
+  virtual ~GetLogLevelResponse();
+
+  GetLogLevelResponse(const GetLogLevelResponse& from);
+
+  inline GetLogLevelResponse& operator=(const GetLogLevelResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  GetLogLevelResponse(GetLogLevelResponse&& from) noexcept
+    : GetLogLevelResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline GetLogLevelResponse& operator=(GetLogLevelResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const GetLogLevelResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const GetLogLevelResponse* internal_default_instance() {
+    return reinterpret_cast<const GetLogLevelResponse*>(
+               &_GetLogLevelResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    20;
+
+  void Swap(GetLogLevelResponse* other);
+  friend void swap(GetLogLevelResponse& a, GetLogLevelResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline GetLogLevelResponse* New() const final {
+    return CreateMaybeMessage<GetLogLevelResponse>(nullptr);
+  }
+
+  GetLogLevelResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<GetLogLevelResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const GetLogLevelResponse& from);
+  void MergeFrom(const GetLogLevelResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(GetLogLevelResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef GetLogLevelResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    GetLogLevelResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    GetLogLevelResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    GetLogLevelResponse_Reason_INTERNAL_ERROR;
+  static const Reason UNKNOWN_LOG_ENTITY =
+    GetLogLevelResponse_Reason_UNKNOWN_LOG_ENTITY;
+  static const Reason DEVICE_UNREACHABLE =
+    GetLogLevelResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return GetLogLevelResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    GetLogLevelResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    GetLogLevelResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    GetLogLevelResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return GetLogLevelResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return GetLogLevelResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return GetLogLevelResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // repeated .dmi.EntitiesLogLevel logLevels = 2;
+  int loglevels_size() const;
+  void clear_loglevels();
+  static const int kLogLevelsFieldNumber = 2;
+  ::dmi::EntitiesLogLevel* mutable_loglevels(int index);
+  ::google::protobuf::RepeatedPtrField< ::dmi::EntitiesLogLevel >*
+      mutable_loglevels();
+  const ::dmi::EntitiesLogLevel& loglevels(int index) const;
+  ::dmi::EntitiesLogLevel* add_loglevels();
+  const ::google::protobuf::RepeatedPtrField< ::dmi::EntitiesLogLevel >&
+      loglevels() const;
+
+  // string reason_detail = 5;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 5;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // .dmi.Status status = 3;
+  void clear_status();
+  static const int kStatusFieldNumber = 3;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.GetLogLevelResponse.Reason reason = 4;
+  void clear_reason();
+  static const int kReasonFieldNumber = 4;
+  ::dmi::GetLogLevelResponse_Reason reason() const;
+  void set_reason(::dmi::GetLogLevelResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.GetLogLevelResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::RepeatedPtrField< ::dmi::EntitiesLogLevel > loglevels_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  ::dmi::Uuid* device_uuid_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class GetLoggableEntitiesRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.GetLoggableEntitiesRequest) */ {
+ public:
+  GetLoggableEntitiesRequest();
+  virtual ~GetLoggableEntitiesRequest();
+
+  GetLoggableEntitiesRequest(const GetLoggableEntitiesRequest& from);
+
+  inline GetLoggableEntitiesRequest& operator=(const GetLoggableEntitiesRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  GetLoggableEntitiesRequest(GetLoggableEntitiesRequest&& from) noexcept
+    : GetLoggableEntitiesRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline GetLoggableEntitiesRequest& operator=(GetLoggableEntitiesRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const GetLoggableEntitiesRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const GetLoggableEntitiesRequest* internal_default_instance() {
+    return reinterpret_cast<const GetLoggableEntitiesRequest*>(
+               &_GetLoggableEntitiesRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    21;
+
+  void Swap(GetLoggableEntitiesRequest* other);
+  friend void swap(GetLoggableEntitiesRequest& a, GetLoggableEntitiesRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline GetLoggableEntitiesRequest* New() const final {
+    return CreateMaybeMessage<GetLoggableEntitiesRequest>(nullptr);
+  }
+
+  GetLoggableEntitiesRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<GetLoggableEntitiesRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const GetLoggableEntitiesRequest& from);
+  void MergeFrom(const GetLoggableEntitiesRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(GetLoggableEntitiesRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.GetLoggableEntitiesRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::Uuid* device_uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmanagement_5fservice_2eproto;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// PhysicalInventoryRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool PhysicalInventoryRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& PhysicalInventoryRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.PhysicalInventoryRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* PhysicalInventoryRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.PhysicalInventoryRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* PhysicalInventoryRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.PhysicalInventoryRequest.device_uuid)
+  return device_uuid_;
+}
+inline void PhysicalInventoryRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.PhysicalInventoryRequest.device_uuid)
+}
+
+// -------------------------------------------------------------------
+
+// PhysicalInventoryResponse
+
+// .dmi.Status status = 1;
+inline void PhysicalInventoryResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status PhysicalInventoryResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.PhysicalInventoryResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void PhysicalInventoryResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.PhysicalInventoryResponse.status)
+}
+
+// .dmi.PhysicalInventoryResponse.Reason reason = 2;
+inline void PhysicalInventoryResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::PhysicalInventoryResponse_Reason PhysicalInventoryResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.PhysicalInventoryResponse.reason)
+  return static_cast< ::dmi::PhysicalInventoryResponse_Reason >(reason_);
+}
+inline void PhysicalInventoryResponse::set_reason(::dmi::PhysicalInventoryResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.PhysicalInventoryResponse.reason)
+}
+
+// .dmi.Hardware inventory = 3;
+inline bool PhysicalInventoryResponse::has_inventory() const {
+  return this != internal_default_instance() && inventory_ != nullptr;
+}
+inline const ::dmi::Hardware& PhysicalInventoryResponse::inventory() const {
+  const ::dmi::Hardware* p = inventory_;
+  // @@protoc_insertion_point(field_get:dmi.PhysicalInventoryResponse.inventory)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Hardware*>(
+      &::dmi::_Hardware_default_instance_);
+}
+inline ::dmi::Hardware* PhysicalInventoryResponse::release_inventory() {
+  // @@protoc_insertion_point(field_release:dmi.PhysicalInventoryResponse.inventory)
+  
+  ::dmi::Hardware* temp = inventory_;
+  inventory_ = nullptr;
+  return temp;
+}
+inline ::dmi::Hardware* PhysicalInventoryResponse::mutable_inventory() {
+  
+  if (inventory_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Hardware>(GetArenaNoVirtual());
+    inventory_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.PhysicalInventoryResponse.inventory)
+  return inventory_;
+}
+inline void PhysicalInventoryResponse::set_allocated_inventory(::dmi::Hardware* inventory) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(inventory_);
+  }
+  if (inventory) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      inventory = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, inventory, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  inventory_ = inventory;
+  // @@protoc_insertion_point(field_set_allocated:dmi.PhysicalInventoryResponse.inventory)
+}
+
+// string reason_detail = 4;
+inline void PhysicalInventoryResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& PhysicalInventoryResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.PhysicalInventoryResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void PhysicalInventoryResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.PhysicalInventoryResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void PhysicalInventoryResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.PhysicalInventoryResponse.reason_detail)
+}
+#endif
+inline void PhysicalInventoryResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.PhysicalInventoryResponse.reason_detail)
+}
+inline void PhysicalInventoryResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.PhysicalInventoryResponse.reason_detail)
+}
+inline ::std::string* PhysicalInventoryResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.PhysicalInventoryResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* PhysicalInventoryResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.PhysicalInventoryResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void PhysicalInventoryResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.PhysicalInventoryResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// HWComponentInfoGetRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool HWComponentInfoGetRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& HWComponentInfoGetRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoGetRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* HWComponentInfoGetRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.HWComponentInfoGetRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* HWComponentInfoGetRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.HWComponentInfoGetRequest.device_uuid)
+  return device_uuid_;
+}
+inline void HWComponentInfoGetRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.HWComponentInfoGetRequest.device_uuid)
+}
+
+// .dmi.Uuid component_uuid = 2;
+inline bool HWComponentInfoGetRequest::has_component_uuid() const {
+  return this != internal_default_instance() && component_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& HWComponentInfoGetRequest::component_uuid() const {
+  const ::dmi::Uuid* p = component_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoGetRequest.component_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* HWComponentInfoGetRequest::release_component_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.HWComponentInfoGetRequest.component_uuid)
+  
+  ::dmi::Uuid* temp = component_uuid_;
+  component_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* HWComponentInfoGetRequest::mutable_component_uuid() {
+  
+  if (component_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    component_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.HWComponentInfoGetRequest.component_uuid)
+  return component_uuid_;
+}
+inline void HWComponentInfoGetRequest::set_allocated_component_uuid(::dmi::Uuid* component_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(component_uuid_);
+  }
+  if (component_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      component_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, component_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  component_uuid_ = component_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.HWComponentInfoGetRequest.component_uuid)
+}
+
+// string component_name = 3;
+inline void HWComponentInfoGetRequest::clear_component_name() {
+  component_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& HWComponentInfoGetRequest::component_name() const {
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoGetRequest.component_name)
+  return component_name_.GetNoArena();
+}
+inline void HWComponentInfoGetRequest::set_component_name(const ::std::string& value) {
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.HWComponentInfoGetRequest.component_name)
+}
+#if LANG_CXX11
+inline void HWComponentInfoGetRequest::set_component_name(::std::string&& value) {
+  
+  component_name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.HWComponentInfoGetRequest.component_name)
+}
+#endif
+inline void HWComponentInfoGetRequest::set_component_name(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.HWComponentInfoGetRequest.component_name)
+}
+inline void HWComponentInfoGetRequest::set_component_name(const char* value, size_t size) {
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.HWComponentInfoGetRequest.component_name)
+}
+inline ::std::string* HWComponentInfoGetRequest::mutable_component_name() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.HWComponentInfoGetRequest.component_name)
+  return component_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* HWComponentInfoGetRequest::release_component_name() {
+  // @@protoc_insertion_point(field_release:dmi.HWComponentInfoGetRequest.component_name)
+  
+  return component_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void HWComponentInfoGetRequest::set_allocated_component_name(::std::string* component_name) {
+  if (component_name != nullptr) {
+    
+  } else {
+    
+  }
+  component_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), component_name);
+  // @@protoc_insertion_point(field_set_allocated:dmi.HWComponentInfoGetRequest.component_name)
+}
+
+// -------------------------------------------------------------------
+
+// HWComponentInfoGetResponse
+
+// .dmi.Status status = 1;
+inline void HWComponentInfoGetResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status HWComponentInfoGetResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoGetResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void HWComponentInfoGetResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.HWComponentInfoGetResponse.status)
+}
+
+// .dmi.HWComponentInfoGetResponse.Reason reason = 2;
+inline void HWComponentInfoGetResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::HWComponentInfoGetResponse_Reason HWComponentInfoGetResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoGetResponse.reason)
+  return static_cast< ::dmi::HWComponentInfoGetResponse_Reason >(reason_);
+}
+inline void HWComponentInfoGetResponse::set_reason(::dmi::HWComponentInfoGetResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.HWComponentInfoGetResponse.reason)
+}
+
+// .dmi.Component component = 3;
+inline bool HWComponentInfoGetResponse::has_component() const {
+  return this != internal_default_instance() && component_ != nullptr;
+}
+inline const ::dmi::Component& HWComponentInfoGetResponse::component() const {
+  const ::dmi::Component* p = component_;
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoGetResponse.component)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Component*>(
+      &::dmi::_Component_default_instance_);
+}
+inline ::dmi::Component* HWComponentInfoGetResponse::release_component() {
+  // @@protoc_insertion_point(field_release:dmi.HWComponentInfoGetResponse.component)
+  
+  ::dmi::Component* temp = component_;
+  component_ = nullptr;
+  return temp;
+}
+inline ::dmi::Component* HWComponentInfoGetResponse::mutable_component() {
+  
+  if (component_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Component>(GetArenaNoVirtual());
+    component_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.HWComponentInfoGetResponse.component)
+  return component_;
+}
+inline void HWComponentInfoGetResponse::set_allocated_component(::dmi::Component* component) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(component_);
+  }
+  if (component) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      component = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, component, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  component_ = component;
+  // @@protoc_insertion_point(field_set_allocated:dmi.HWComponentInfoGetResponse.component)
+}
+
+// string reason_detail = 4;
+inline void HWComponentInfoGetResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& HWComponentInfoGetResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoGetResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void HWComponentInfoGetResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.HWComponentInfoGetResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void HWComponentInfoGetResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.HWComponentInfoGetResponse.reason_detail)
+}
+#endif
+inline void HWComponentInfoGetResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.HWComponentInfoGetResponse.reason_detail)
+}
+inline void HWComponentInfoGetResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.HWComponentInfoGetResponse.reason_detail)
+}
+inline ::std::string* HWComponentInfoGetResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.HWComponentInfoGetResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* HWComponentInfoGetResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.HWComponentInfoGetResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void HWComponentInfoGetResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.HWComponentInfoGetResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// HWComponentInfoSetRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool HWComponentInfoSetRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& HWComponentInfoSetRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoSetRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* HWComponentInfoSetRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.HWComponentInfoSetRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* HWComponentInfoSetRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.HWComponentInfoSetRequest.device_uuid)
+  return device_uuid_;
+}
+inline void HWComponentInfoSetRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.HWComponentInfoSetRequest.device_uuid)
+}
+
+// .dmi.Uuid component_uuid = 2;
+inline bool HWComponentInfoSetRequest::has_component_uuid() const {
+  return this != internal_default_instance() && component_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& HWComponentInfoSetRequest::component_uuid() const {
+  const ::dmi::Uuid* p = component_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoSetRequest.component_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* HWComponentInfoSetRequest::release_component_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.HWComponentInfoSetRequest.component_uuid)
+  
+  ::dmi::Uuid* temp = component_uuid_;
+  component_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* HWComponentInfoSetRequest::mutable_component_uuid() {
+  
+  if (component_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    component_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.HWComponentInfoSetRequest.component_uuid)
+  return component_uuid_;
+}
+inline void HWComponentInfoSetRequest::set_allocated_component_uuid(::dmi::Uuid* component_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(component_uuid_);
+  }
+  if (component_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      component_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, component_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  component_uuid_ = component_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.HWComponentInfoSetRequest.component_uuid)
+}
+
+// string component_name = 3;
+inline void HWComponentInfoSetRequest::clear_component_name() {
+  component_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& HWComponentInfoSetRequest::component_name() const {
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoSetRequest.component_name)
+  return component_name_.GetNoArena();
+}
+inline void HWComponentInfoSetRequest::set_component_name(const ::std::string& value) {
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.HWComponentInfoSetRequest.component_name)
+}
+#if LANG_CXX11
+inline void HWComponentInfoSetRequest::set_component_name(::std::string&& value) {
+  
+  component_name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.HWComponentInfoSetRequest.component_name)
+}
+#endif
+inline void HWComponentInfoSetRequest::set_component_name(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.HWComponentInfoSetRequest.component_name)
+}
+inline void HWComponentInfoSetRequest::set_component_name(const char* value, size_t size) {
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.HWComponentInfoSetRequest.component_name)
+}
+inline ::std::string* HWComponentInfoSetRequest::mutable_component_name() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.HWComponentInfoSetRequest.component_name)
+  return component_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* HWComponentInfoSetRequest::release_component_name() {
+  // @@protoc_insertion_point(field_release:dmi.HWComponentInfoSetRequest.component_name)
+  
+  return component_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void HWComponentInfoSetRequest::set_allocated_component_name(::std::string* component_name) {
+  if (component_name != nullptr) {
+    
+  } else {
+    
+  }
+  component_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), component_name);
+  // @@protoc_insertion_point(field_set_allocated:dmi.HWComponentInfoSetRequest.component_name)
+}
+
+// .dmi.ModifiableComponent changes = 4;
+inline bool HWComponentInfoSetRequest::has_changes() const {
+  return this != internal_default_instance() && changes_ != nullptr;
+}
+inline const ::dmi::ModifiableComponent& HWComponentInfoSetRequest::changes() const {
+  const ::dmi::ModifiableComponent* p = changes_;
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoSetRequest.changes)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ModifiableComponent*>(
+      &::dmi::_ModifiableComponent_default_instance_);
+}
+inline ::dmi::ModifiableComponent* HWComponentInfoSetRequest::release_changes() {
+  // @@protoc_insertion_point(field_release:dmi.HWComponentInfoSetRequest.changes)
+  
+  ::dmi::ModifiableComponent* temp = changes_;
+  changes_ = nullptr;
+  return temp;
+}
+inline ::dmi::ModifiableComponent* HWComponentInfoSetRequest::mutable_changes() {
+  
+  if (changes_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ModifiableComponent>(GetArenaNoVirtual());
+    changes_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.HWComponentInfoSetRequest.changes)
+  return changes_;
+}
+inline void HWComponentInfoSetRequest::set_allocated_changes(::dmi::ModifiableComponent* changes) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(changes_);
+  }
+  if (changes) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      changes = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, changes, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  changes_ = changes;
+  // @@protoc_insertion_point(field_set_allocated:dmi.HWComponentInfoSetRequest.changes)
+}
+
+// -------------------------------------------------------------------
+
+// HWComponentInfoSetResponse
+
+// .dmi.Status status = 1;
+inline void HWComponentInfoSetResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status HWComponentInfoSetResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoSetResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void HWComponentInfoSetResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.HWComponentInfoSetResponse.status)
+}
+
+// .dmi.HWComponentInfoSetResponse.Reason reason = 2;
+inline void HWComponentInfoSetResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::HWComponentInfoSetResponse_Reason HWComponentInfoSetResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoSetResponse.reason)
+  return static_cast< ::dmi::HWComponentInfoSetResponse_Reason >(reason_);
+}
+inline void HWComponentInfoSetResponse::set_reason(::dmi::HWComponentInfoSetResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.HWComponentInfoSetResponse.reason)
+}
+
+// string reason_detail = 3;
+inline void HWComponentInfoSetResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& HWComponentInfoSetResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.HWComponentInfoSetResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void HWComponentInfoSetResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.HWComponentInfoSetResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void HWComponentInfoSetResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.HWComponentInfoSetResponse.reason_detail)
+}
+#endif
+inline void HWComponentInfoSetResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.HWComponentInfoSetResponse.reason_detail)
+}
+inline void HWComponentInfoSetResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.HWComponentInfoSetResponse.reason_detail)
+}
+inline ::std::string* HWComponentInfoSetResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.HWComponentInfoSetResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* HWComponentInfoSetResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.HWComponentInfoSetResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void HWComponentInfoSetResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.HWComponentInfoSetResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// StartManagingDeviceResponse
+
+// .dmi.Status status = 1;
+inline void StartManagingDeviceResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status StartManagingDeviceResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.StartManagingDeviceResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void StartManagingDeviceResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.StartManagingDeviceResponse.status)
+}
+
+// .dmi.StartManagingDeviceResponse.Reason reason = 2;
+inline void StartManagingDeviceResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::StartManagingDeviceResponse_Reason StartManagingDeviceResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.StartManagingDeviceResponse.reason)
+  return static_cast< ::dmi::StartManagingDeviceResponse_Reason >(reason_);
+}
+inline void StartManagingDeviceResponse::set_reason(::dmi::StartManagingDeviceResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.StartManagingDeviceResponse.reason)
+}
+
+// .dmi.Uuid device_uuid = 3;
+inline bool StartManagingDeviceResponse::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& StartManagingDeviceResponse::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.StartManagingDeviceResponse.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* StartManagingDeviceResponse::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.StartManagingDeviceResponse.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* StartManagingDeviceResponse::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.StartManagingDeviceResponse.device_uuid)
+  return device_uuid_;
+}
+inline void StartManagingDeviceResponse::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.StartManagingDeviceResponse.device_uuid)
+}
+
+// string reason_detail = 4;
+inline void StartManagingDeviceResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& StartManagingDeviceResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.StartManagingDeviceResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void StartManagingDeviceResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.StartManagingDeviceResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void StartManagingDeviceResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.StartManagingDeviceResponse.reason_detail)
+}
+#endif
+inline void StartManagingDeviceResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.StartManagingDeviceResponse.reason_detail)
+}
+inline void StartManagingDeviceResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.StartManagingDeviceResponse.reason_detail)
+}
+inline ::std::string* StartManagingDeviceResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.StartManagingDeviceResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* StartManagingDeviceResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.StartManagingDeviceResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void StartManagingDeviceResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.StartManagingDeviceResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// StopManagingDeviceRequest
+
+// string name = 1;
+inline void StopManagingDeviceRequest::clear_name() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& StopManagingDeviceRequest::name() const {
+  // @@protoc_insertion_point(field_get:dmi.StopManagingDeviceRequest.name)
+  return name_.GetNoArena();
+}
+inline void StopManagingDeviceRequest::set_name(const ::std::string& value) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.StopManagingDeviceRequest.name)
+}
+#if LANG_CXX11
+inline void StopManagingDeviceRequest::set_name(::std::string&& value) {
+  
+  name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.StopManagingDeviceRequest.name)
+}
+#endif
+inline void StopManagingDeviceRequest::set_name(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.StopManagingDeviceRequest.name)
+}
+inline void StopManagingDeviceRequest::set_name(const char* value, size_t size) {
+  
+  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.StopManagingDeviceRequest.name)
+}
+inline ::std::string* StopManagingDeviceRequest::mutable_name() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.StopManagingDeviceRequest.name)
+  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* StopManagingDeviceRequest::release_name() {
+  // @@protoc_insertion_point(field_release:dmi.StopManagingDeviceRequest.name)
+  
+  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void StopManagingDeviceRequest::set_allocated_name(::std::string* name) {
+  if (name != nullptr) {
+    
+  } else {
+    
+  }
+  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+  // @@protoc_insertion_point(field_set_allocated:dmi.StopManagingDeviceRequest.name)
+}
+
+// -------------------------------------------------------------------
+
+// StopManagingDeviceResponse
+
+// .dmi.Status status = 1;
+inline void StopManagingDeviceResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status StopManagingDeviceResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.StopManagingDeviceResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void StopManagingDeviceResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.StopManagingDeviceResponse.status)
+}
+
+// .dmi.StopManagingDeviceResponse.Reason reason = 2;
+inline void StopManagingDeviceResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::StopManagingDeviceResponse_Reason StopManagingDeviceResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.StopManagingDeviceResponse.reason)
+  return static_cast< ::dmi::StopManagingDeviceResponse_Reason >(reason_);
+}
+inline void StopManagingDeviceResponse::set_reason(::dmi::StopManagingDeviceResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.StopManagingDeviceResponse.reason)
+}
+
+// string reason_detail = 3;
+inline void StopManagingDeviceResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& StopManagingDeviceResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.StopManagingDeviceResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void StopManagingDeviceResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.StopManagingDeviceResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void StopManagingDeviceResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.StopManagingDeviceResponse.reason_detail)
+}
+#endif
+inline void StopManagingDeviceResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.StopManagingDeviceResponse.reason_detail)
+}
+inline void StopManagingDeviceResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.StopManagingDeviceResponse.reason_detail)
+}
+inline ::std::string* StopManagingDeviceResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.StopManagingDeviceResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* StopManagingDeviceResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.StopManagingDeviceResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void StopManagingDeviceResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.StopManagingDeviceResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// ManagedDeviceInfo
+
+// .dmi.ModifiableComponent info = 1;
+inline bool ManagedDeviceInfo::has_info() const {
+  return this != internal_default_instance() && info_ != nullptr;
+}
+inline const ::dmi::ModifiableComponent& ManagedDeviceInfo::info() const {
+  const ::dmi::ModifiableComponent* p = info_;
+  // @@protoc_insertion_point(field_get:dmi.ManagedDeviceInfo.info)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ModifiableComponent*>(
+      &::dmi::_ModifiableComponent_default_instance_);
+}
+inline ::dmi::ModifiableComponent* ManagedDeviceInfo::release_info() {
+  // @@protoc_insertion_point(field_release:dmi.ManagedDeviceInfo.info)
+  
+  ::dmi::ModifiableComponent* temp = info_;
+  info_ = nullptr;
+  return temp;
+}
+inline ::dmi::ModifiableComponent* ManagedDeviceInfo::mutable_info() {
+  
+  if (info_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ModifiableComponent>(GetArenaNoVirtual());
+    info_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ManagedDeviceInfo.info)
+  return info_;
+}
+inline void ManagedDeviceInfo::set_allocated_info(::dmi::ModifiableComponent* info) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(info_);
+  }
+  if (info) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      info = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, info, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  info_ = info;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ManagedDeviceInfo.info)
+}
+
+// .dmi.Uuid device_uuid = 2;
+inline bool ManagedDeviceInfo::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& ManagedDeviceInfo::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.ManagedDeviceInfo.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* ManagedDeviceInfo::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.ManagedDeviceInfo.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* ManagedDeviceInfo::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ManagedDeviceInfo.device_uuid)
+  return device_uuid_;
+}
+inline void ManagedDeviceInfo::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ManagedDeviceInfo.device_uuid)
+}
+
+// -------------------------------------------------------------------
+
+// ManagedDevicesResponse
+
+// .dmi.Status status = 1;
+inline void ManagedDevicesResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status ManagedDevicesResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.ManagedDevicesResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void ManagedDevicesResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ManagedDevicesResponse.status)
+}
+
+// .dmi.ManagedDevicesResponse.Reason reason = 2;
+inline void ManagedDevicesResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::ManagedDevicesResponse_Reason ManagedDevicesResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.ManagedDevicesResponse.reason)
+  return static_cast< ::dmi::ManagedDevicesResponse_Reason >(reason_);
+}
+inline void ManagedDevicesResponse::set_reason(::dmi::ManagedDevicesResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ManagedDevicesResponse.reason)
+}
+
+// repeated .dmi.ManagedDeviceInfo devices = 3;
+inline int ManagedDevicesResponse::devices_size() const {
+  return devices_.size();
+}
+inline void ManagedDevicesResponse::clear_devices() {
+  devices_.Clear();
+}
+inline ::dmi::ManagedDeviceInfo* ManagedDevicesResponse::mutable_devices(int index) {
+  // @@protoc_insertion_point(field_mutable:dmi.ManagedDevicesResponse.devices)
+  return devices_.Mutable(index);
+}
+inline ::google::protobuf::RepeatedPtrField< ::dmi::ManagedDeviceInfo >*
+ManagedDevicesResponse::mutable_devices() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.ManagedDevicesResponse.devices)
+  return &devices_;
+}
+inline const ::dmi::ManagedDeviceInfo& ManagedDevicesResponse::devices(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.ManagedDevicesResponse.devices)
+  return devices_.Get(index);
+}
+inline ::dmi::ManagedDeviceInfo* ManagedDevicesResponse::add_devices() {
+  // @@protoc_insertion_point(field_add:dmi.ManagedDevicesResponse.devices)
+  return devices_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::dmi::ManagedDeviceInfo >&
+ManagedDevicesResponse::devices() const {
+  // @@protoc_insertion_point(field_list:dmi.ManagedDevicesResponse.devices)
+  return devices_;
+}
+
+// -------------------------------------------------------------------
+
+// SetLoggingEndpointRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool SetLoggingEndpointRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& SetLoggingEndpointRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.SetLoggingEndpointRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* SetLoggingEndpointRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.SetLoggingEndpointRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* SetLoggingEndpointRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.SetLoggingEndpointRequest.device_uuid)
+  return device_uuid_;
+}
+inline void SetLoggingEndpointRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.SetLoggingEndpointRequest.device_uuid)
+}
+
+// string logging_endpoint = 2;
+inline void SetLoggingEndpointRequest::clear_logging_endpoint() {
+  logging_endpoint_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& SetLoggingEndpointRequest::logging_endpoint() const {
+  // @@protoc_insertion_point(field_get:dmi.SetLoggingEndpointRequest.logging_endpoint)
+  return logging_endpoint_.GetNoArena();
+}
+inline void SetLoggingEndpointRequest::set_logging_endpoint(const ::std::string& value) {
+  
+  logging_endpoint_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.SetLoggingEndpointRequest.logging_endpoint)
+}
+#if LANG_CXX11
+inline void SetLoggingEndpointRequest::set_logging_endpoint(::std::string&& value) {
+  
+  logging_endpoint_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.SetLoggingEndpointRequest.logging_endpoint)
+}
+#endif
+inline void SetLoggingEndpointRequest::set_logging_endpoint(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  logging_endpoint_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.SetLoggingEndpointRequest.logging_endpoint)
+}
+inline void SetLoggingEndpointRequest::set_logging_endpoint(const char* value, size_t size) {
+  
+  logging_endpoint_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.SetLoggingEndpointRequest.logging_endpoint)
+}
+inline ::std::string* SetLoggingEndpointRequest::mutable_logging_endpoint() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.SetLoggingEndpointRequest.logging_endpoint)
+  return logging_endpoint_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* SetLoggingEndpointRequest::release_logging_endpoint() {
+  // @@protoc_insertion_point(field_release:dmi.SetLoggingEndpointRequest.logging_endpoint)
+  
+  return logging_endpoint_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SetLoggingEndpointRequest::set_allocated_logging_endpoint(::std::string* logging_endpoint) {
+  if (logging_endpoint != nullptr) {
+    
+  } else {
+    
+  }
+  logging_endpoint_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), logging_endpoint);
+  // @@protoc_insertion_point(field_set_allocated:dmi.SetLoggingEndpointRequest.logging_endpoint)
+}
+
+// string logging_protocol = 3;
+inline void SetLoggingEndpointRequest::clear_logging_protocol() {
+  logging_protocol_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& SetLoggingEndpointRequest::logging_protocol() const {
+  // @@protoc_insertion_point(field_get:dmi.SetLoggingEndpointRequest.logging_protocol)
+  return logging_protocol_.GetNoArena();
+}
+inline void SetLoggingEndpointRequest::set_logging_protocol(const ::std::string& value) {
+  
+  logging_protocol_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.SetLoggingEndpointRequest.logging_protocol)
+}
+#if LANG_CXX11
+inline void SetLoggingEndpointRequest::set_logging_protocol(::std::string&& value) {
+  
+  logging_protocol_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.SetLoggingEndpointRequest.logging_protocol)
+}
+#endif
+inline void SetLoggingEndpointRequest::set_logging_protocol(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  logging_protocol_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.SetLoggingEndpointRequest.logging_protocol)
+}
+inline void SetLoggingEndpointRequest::set_logging_protocol(const char* value, size_t size) {
+  
+  logging_protocol_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.SetLoggingEndpointRequest.logging_protocol)
+}
+inline ::std::string* SetLoggingEndpointRequest::mutable_logging_protocol() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.SetLoggingEndpointRequest.logging_protocol)
+  return logging_protocol_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* SetLoggingEndpointRequest::release_logging_protocol() {
+  // @@protoc_insertion_point(field_release:dmi.SetLoggingEndpointRequest.logging_protocol)
+  
+  return logging_protocol_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SetLoggingEndpointRequest::set_allocated_logging_protocol(::std::string* logging_protocol) {
+  if (logging_protocol != nullptr) {
+    
+  } else {
+    
+  }
+  logging_protocol_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), logging_protocol);
+  // @@protoc_insertion_point(field_set_allocated:dmi.SetLoggingEndpointRequest.logging_protocol)
+}
+
+// -------------------------------------------------------------------
+
+// SetRemoteEndpointResponse
+
+// .dmi.Status status = 1;
+inline void SetRemoteEndpointResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status SetRemoteEndpointResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.SetRemoteEndpointResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void SetRemoteEndpointResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.SetRemoteEndpointResponse.status)
+}
+
+// .dmi.SetRemoteEndpointResponse.Reason reason = 2;
+inline void SetRemoteEndpointResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::SetRemoteEndpointResponse_Reason SetRemoteEndpointResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.SetRemoteEndpointResponse.reason)
+  return static_cast< ::dmi::SetRemoteEndpointResponse_Reason >(reason_);
+}
+inline void SetRemoteEndpointResponse::set_reason(::dmi::SetRemoteEndpointResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.SetRemoteEndpointResponse.reason)
+}
+
+// string reason_detail = 3;
+inline void SetRemoteEndpointResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& SetRemoteEndpointResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.SetRemoteEndpointResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void SetRemoteEndpointResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.SetRemoteEndpointResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void SetRemoteEndpointResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.SetRemoteEndpointResponse.reason_detail)
+}
+#endif
+inline void SetRemoteEndpointResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.SetRemoteEndpointResponse.reason_detail)
+}
+inline void SetRemoteEndpointResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.SetRemoteEndpointResponse.reason_detail)
+}
+inline ::std::string* SetRemoteEndpointResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.SetRemoteEndpointResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* SetRemoteEndpointResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.SetRemoteEndpointResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SetRemoteEndpointResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.SetRemoteEndpointResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// GetLoggingEndpointResponse
+
+// .dmi.Status status = 1;
+inline void GetLoggingEndpointResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status GetLoggingEndpointResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.GetLoggingEndpointResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void GetLoggingEndpointResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.GetLoggingEndpointResponse.status)
+}
+
+// .dmi.GetLoggingEndpointResponse.Reason reason = 2;
+inline void GetLoggingEndpointResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::GetLoggingEndpointResponse_Reason GetLoggingEndpointResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.GetLoggingEndpointResponse.reason)
+  return static_cast< ::dmi::GetLoggingEndpointResponse_Reason >(reason_);
+}
+inline void GetLoggingEndpointResponse::set_reason(::dmi::GetLoggingEndpointResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.GetLoggingEndpointResponse.reason)
+}
+
+// string logging_endpoint = 3;
+inline void GetLoggingEndpointResponse::clear_logging_endpoint() {
+  logging_endpoint_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& GetLoggingEndpointResponse::logging_endpoint() const {
+  // @@protoc_insertion_point(field_get:dmi.GetLoggingEndpointResponse.logging_endpoint)
+  return logging_endpoint_.GetNoArena();
+}
+inline void GetLoggingEndpointResponse::set_logging_endpoint(const ::std::string& value) {
+  
+  logging_endpoint_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.GetLoggingEndpointResponse.logging_endpoint)
+}
+#if LANG_CXX11
+inline void GetLoggingEndpointResponse::set_logging_endpoint(::std::string&& value) {
+  
+  logging_endpoint_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.GetLoggingEndpointResponse.logging_endpoint)
+}
+#endif
+inline void GetLoggingEndpointResponse::set_logging_endpoint(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  logging_endpoint_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.GetLoggingEndpointResponse.logging_endpoint)
+}
+inline void GetLoggingEndpointResponse::set_logging_endpoint(const char* value, size_t size) {
+  
+  logging_endpoint_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.GetLoggingEndpointResponse.logging_endpoint)
+}
+inline ::std::string* GetLoggingEndpointResponse::mutable_logging_endpoint() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.GetLoggingEndpointResponse.logging_endpoint)
+  return logging_endpoint_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* GetLoggingEndpointResponse::release_logging_endpoint() {
+  // @@protoc_insertion_point(field_release:dmi.GetLoggingEndpointResponse.logging_endpoint)
+  
+  return logging_endpoint_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void GetLoggingEndpointResponse::set_allocated_logging_endpoint(::std::string* logging_endpoint) {
+  if (logging_endpoint != nullptr) {
+    
+  } else {
+    
+  }
+  logging_endpoint_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), logging_endpoint);
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetLoggingEndpointResponse.logging_endpoint)
+}
+
+// string logging_protocol = 4;
+inline void GetLoggingEndpointResponse::clear_logging_protocol() {
+  logging_protocol_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& GetLoggingEndpointResponse::logging_protocol() const {
+  // @@protoc_insertion_point(field_get:dmi.GetLoggingEndpointResponse.logging_protocol)
+  return logging_protocol_.GetNoArena();
+}
+inline void GetLoggingEndpointResponse::set_logging_protocol(const ::std::string& value) {
+  
+  logging_protocol_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.GetLoggingEndpointResponse.logging_protocol)
+}
+#if LANG_CXX11
+inline void GetLoggingEndpointResponse::set_logging_protocol(::std::string&& value) {
+  
+  logging_protocol_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.GetLoggingEndpointResponse.logging_protocol)
+}
+#endif
+inline void GetLoggingEndpointResponse::set_logging_protocol(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  logging_protocol_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.GetLoggingEndpointResponse.logging_protocol)
+}
+inline void GetLoggingEndpointResponse::set_logging_protocol(const char* value, size_t size) {
+  
+  logging_protocol_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.GetLoggingEndpointResponse.logging_protocol)
+}
+inline ::std::string* GetLoggingEndpointResponse::mutable_logging_protocol() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.GetLoggingEndpointResponse.logging_protocol)
+  return logging_protocol_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* GetLoggingEndpointResponse::release_logging_protocol() {
+  // @@protoc_insertion_point(field_release:dmi.GetLoggingEndpointResponse.logging_protocol)
+  
+  return logging_protocol_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void GetLoggingEndpointResponse::set_allocated_logging_protocol(::std::string* logging_protocol) {
+  if (logging_protocol != nullptr) {
+    
+  } else {
+    
+  }
+  logging_protocol_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), logging_protocol);
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetLoggingEndpointResponse.logging_protocol)
+}
+
+// string reason_detail = 5;
+inline void GetLoggingEndpointResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& GetLoggingEndpointResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.GetLoggingEndpointResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void GetLoggingEndpointResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.GetLoggingEndpointResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void GetLoggingEndpointResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.GetLoggingEndpointResponse.reason_detail)
+}
+#endif
+inline void GetLoggingEndpointResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.GetLoggingEndpointResponse.reason_detail)
+}
+inline void GetLoggingEndpointResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.GetLoggingEndpointResponse.reason_detail)
+}
+inline ::std::string* GetLoggingEndpointResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.GetLoggingEndpointResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* GetLoggingEndpointResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.GetLoggingEndpointResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void GetLoggingEndpointResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetLoggingEndpointResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// SetMsgBusEndpointRequest
+
+// string msgbus_endpoint = 1;
+inline void SetMsgBusEndpointRequest::clear_msgbus_endpoint() {
+  msgbus_endpoint_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& SetMsgBusEndpointRequest::msgbus_endpoint() const {
+  // @@protoc_insertion_point(field_get:dmi.SetMsgBusEndpointRequest.msgbus_endpoint)
+  return msgbus_endpoint_.GetNoArena();
+}
+inline void SetMsgBusEndpointRequest::set_msgbus_endpoint(const ::std::string& value) {
+  
+  msgbus_endpoint_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.SetMsgBusEndpointRequest.msgbus_endpoint)
+}
+#if LANG_CXX11
+inline void SetMsgBusEndpointRequest::set_msgbus_endpoint(::std::string&& value) {
+  
+  msgbus_endpoint_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.SetMsgBusEndpointRequest.msgbus_endpoint)
+}
+#endif
+inline void SetMsgBusEndpointRequest::set_msgbus_endpoint(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  msgbus_endpoint_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.SetMsgBusEndpointRequest.msgbus_endpoint)
+}
+inline void SetMsgBusEndpointRequest::set_msgbus_endpoint(const char* value, size_t size) {
+  
+  msgbus_endpoint_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.SetMsgBusEndpointRequest.msgbus_endpoint)
+}
+inline ::std::string* SetMsgBusEndpointRequest::mutable_msgbus_endpoint() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.SetMsgBusEndpointRequest.msgbus_endpoint)
+  return msgbus_endpoint_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* SetMsgBusEndpointRequest::release_msgbus_endpoint() {
+  // @@protoc_insertion_point(field_release:dmi.SetMsgBusEndpointRequest.msgbus_endpoint)
+  
+  return msgbus_endpoint_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SetMsgBusEndpointRequest::set_allocated_msgbus_endpoint(::std::string* msgbus_endpoint) {
+  if (msgbus_endpoint != nullptr) {
+    
+  } else {
+    
+  }
+  msgbus_endpoint_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), msgbus_endpoint);
+  // @@protoc_insertion_point(field_set_allocated:dmi.SetMsgBusEndpointRequest.msgbus_endpoint)
+}
+
+// -------------------------------------------------------------------
+
+// GetMsgBusEndpointResponse
+
+// .dmi.Status status = 1;
+inline void GetMsgBusEndpointResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status GetMsgBusEndpointResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.GetMsgBusEndpointResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void GetMsgBusEndpointResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.GetMsgBusEndpointResponse.status)
+}
+
+// .dmi.GetMsgBusEndpointResponse.Reason reason = 2;
+inline void GetMsgBusEndpointResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::GetMsgBusEndpointResponse_Reason GetMsgBusEndpointResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.GetMsgBusEndpointResponse.reason)
+  return static_cast< ::dmi::GetMsgBusEndpointResponse_Reason >(reason_);
+}
+inline void GetMsgBusEndpointResponse::set_reason(::dmi::GetMsgBusEndpointResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.GetMsgBusEndpointResponse.reason)
+}
+
+// string msgbus_endpoint = 3;
+inline void GetMsgBusEndpointResponse::clear_msgbus_endpoint() {
+  msgbus_endpoint_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& GetMsgBusEndpointResponse::msgbus_endpoint() const {
+  // @@protoc_insertion_point(field_get:dmi.GetMsgBusEndpointResponse.msgbus_endpoint)
+  return msgbus_endpoint_.GetNoArena();
+}
+inline void GetMsgBusEndpointResponse::set_msgbus_endpoint(const ::std::string& value) {
+  
+  msgbus_endpoint_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.GetMsgBusEndpointResponse.msgbus_endpoint)
+}
+#if LANG_CXX11
+inline void GetMsgBusEndpointResponse::set_msgbus_endpoint(::std::string&& value) {
+  
+  msgbus_endpoint_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.GetMsgBusEndpointResponse.msgbus_endpoint)
+}
+#endif
+inline void GetMsgBusEndpointResponse::set_msgbus_endpoint(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  msgbus_endpoint_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.GetMsgBusEndpointResponse.msgbus_endpoint)
+}
+inline void GetMsgBusEndpointResponse::set_msgbus_endpoint(const char* value, size_t size) {
+  
+  msgbus_endpoint_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.GetMsgBusEndpointResponse.msgbus_endpoint)
+}
+inline ::std::string* GetMsgBusEndpointResponse::mutable_msgbus_endpoint() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.GetMsgBusEndpointResponse.msgbus_endpoint)
+  return msgbus_endpoint_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* GetMsgBusEndpointResponse::release_msgbus_endpoint() {
+  // @@protoc_insertion_point(field_release:dmi.GetMsgBusEndpointResponse.msgbus_endpoint)
+  
+  return msgbus_endpoint_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void GetMsgBusEndpointResponse::set_allocated_msgbus_endpoint(::std::string* msgbus_endpoint) {
+  if (msgbus_endpoint != nullptr) {
+    
+  } else {
+    
+  }
+  msgbus_endpoint_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), msgbus_endpoint);
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetMsgBusEndpointResponse.msgbus_endpoint)
+}
+
+// string reason_detail = 4;
+inline void GetMsgBusEndpointResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& GetMsgBusEndpointResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.GetMsgBusEndpointResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void GetMsgBusEndpointResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.GetMsgBusEndpointResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void GetMsgBusEndpointResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.GetMsgBusEndpointResponse.reason_detail)
+}
+#endif
+inline void GetMsgBusEndpointResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.GetMsgBusEndpointResponse.reason_detail)
+}
+inline void GetMsgBusEndpointResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.GetMsgBusEndpointResponse.reason_detail)
+}
+inline ::std::string* GetMsgBusEndpointResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.GetMsgBusEndpointResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* GetMsgBusEndpointResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.GetMsgBusEndpointResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void GetMsgBusEndpointResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetMsgBusEndpointResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// EntitiesLogLevel
+
+// .dmi.LogLevel logLevel = 1;
+inline void EntitiesLogLevel::clear_loglevel() {
+  loglevel_ = 0;
+}
+inline ::dmi::LogLevel EntitiesLogLevel::loglevel() const {
+  // @@protoc_insertion_point(field_get:dmi.EntitiesLogLevel.logLevel)
+  return static_cast< ::dmi::LogLevel >(loglevel_);
+}
+inline void EntitiesLogLevel::set_loglevel(::dmi::LogLevel value) {
+  
+  loglevel_ = value;
+  // @@protoc_insertion_point(field_set:dmi.EntitiesLogLevel.logLevel)
+}
+
+// repeated string entities = 2;
+inline int EntitiesLogLevel::entities_size() const {
+  return entities_.size();
+}
+inline void EntitiesLogLevel::clear_entities() {
+  entities_.Clear();
+}
+inline const ::std::string& EntitiesLogLevel::entities(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.EntitiesLogLevel.entities)
+  return entities_.Get(index);
+}
+inline ::std::string* EntitiesLogLevel::mutable_entities(int index) {
+  // @@protoc_insertion_point(field_mutable:dmi.EntitiesLogLevel.entities)
+  return entities_.Mutable(index);
+}
+inline void EntitiesLogLevel::set_entities(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:dmi.EntitiesLogLevel.entities)
+  entities_.Mutable(index)->assign(value);
+}
+#if LANG_CXX11
+inline void EntitiesLogLevel::set_entities(int index, ::std::string&& value) {
+  // @@protoc_insertion_point(field_set:dmi.EntitiesLogLevel.entities)
+  entities_.Mutable(index)->assign(std::move(value));
+}
+#endif
+inline void EntitiesLogLevel::set_entities(int index, const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  entities_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:dmi.EntitiesLogLevel.entities)
+}
+inline void EntitiesLogLevel::set_entities(int index, const char* value, size_t size) {
+  entities_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:dmi.EntitiesLogLevel.entities)
+}
+inline ::std::string* EntitiesLogLevel::add_entities() {
+  // @@protoc_insertion_point(field_add_mutable:dmi.EntitiesLogLevel.entities)
+  return entities_.Add();
+}
+inline void EntitiesLogLevel::add_entities(const ::std::string& value) {
+  entities_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:dmi.EntitiesLogLevel.entities)
+}
+#if LANG_CXX11
+inline void EntitiesLogLevel::add_entities(::std::string&& value) {
+  entities_.Add(std::move(value));
+  // @@protoc_insertion_point(field_add:dmi.EntitiesLogLevel.entities)
+}
+#endif
+inline void EntitiesLogLevel::add_entities(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  entities_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:dmi.EntitiesLogLevel.entities)
+}
+inline void EntitiesLogLevel::add_entities(const char* value, size_t size) {
+  entities_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:dmi.EntitiesLogLevel.entities)
+}
+inline const ::google::protobuf::RepeatedPtrField<::std::string>&
+EntitiesLogLevel::entities() const {
+  // @@protoc_insertion_point(field_list:dmi.EntitiesLogLevel.entities)
+  return entities_;
+}
+inline ::google::protobuf::RepeatedPtrField<::std::string>*
+EntitiesLogLevel::mutable_entities() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.EntitiesLogLevel.entities)
+  return &entities_;
+}
+
+// -------------------------------------------------------------------
+
+// SetLogLevelRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool SetLogLevelRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& SetLogLevelRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.SetLogLevelRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* SetLogLevelRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.SetLogLevelRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* SetLogLevelRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.SetLogLevelRequest.device_uuid)
+  return device_uuid_;
+}
+inline void SetLogLevelRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.SetLogLevelRequest.device_uuid)
+}
+
+// repeated .dmi.EntitiesLogLevel loglevels = 2;
+inline int SetLogLevelRequest::loglevels_size() const {
+  return loglevels_.size();
+}
+inline void SetLogLevelRequest::clear_loglevels() {
+  loglevels_.Clear();
+}
+inline ::dmi::EntitiesLogLevel* SetLogLevelRequest::mutable_loglevels(int index) {
+  // @@protoc_insertion_point(field_mutable:dmi.SetLogLevelRequest.loglevels)
+  return loglevels_.Mutable(index);
+}
+inline ::google::protobuf::RepeatedPtrField< ::dmi::EntitiesLogLevel >*
+SetLogLevelRequest::mutable_loglevels() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.SetLogLevelRequest.loglevels)
+  return &loglevels_;
+}
+inline const ::dmi::EntitiesLogLevel& SetLogLevelRequest::loglevels(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.SetLogLevelRequest.loglevels)
+  return loglevels_.Get(index);
+}
+inline ::dmi::EntitiesLogLevel* SetLogLevelRequest::add_loglevels() {
+  // @@protoc_insertion_point(field_add:dmi.SetLogLevelRequest.loglevels)
+  return loglevels_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::dmi::EntitiesLogLevel >&
+SetLogLevelRequest::loglevels() const {
+  // @@protoc_insertion_point(field_list:dmi.SetLogLevelRequest.loglevels)
+  return loglevels_;
+}
+
+// -------------------------------------------------------------------
+
+// SetLogLevelResponse
+
+// .dmi.Uuid device_uuid = 1;
+inline bool SetLogLevelResponse::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& SetLogLevelResponse::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.SetLogLevelResponse.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* SetLogLevelResponse::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.SetLogLevelResponse.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* SetLogLevelResponse::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.SetLogLevelResponse.device_uuid)
+  return device_uuid_;
+}
+inline void SetLogLevelResponse::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.SetLogLevelResponse.device_uuid)
+}
+
+// .dmi.Status status = 2;
+inline void SetLogLevelResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status SetLogLevelResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.SetLogLevelResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void SetLogLevelResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.SetLogLevelResponse.status)
+}
+
+// .dmi.SetLogLevelResponse.Reason reason = 3;
+inline void SetLogLevelResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::SetLogLevelResponse_Reason SetLogLevelResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.SetLogLevelResponse.reason)
+  return static_cast< ::dmi::SetLogLevelResponse_Reason >(reason_);
+}
+inline void SetLogLevelResponse::set_reason(::dmi::SetLogLevelResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.SetLogLevelResponse.reason)
+}
+
+// string reason_detail = 4;
+inline void SetLogLevelResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& SetLogLevelResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.SetLogLevelResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void SetLogLevelResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.SetLogLevelResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void SetLogLevelResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.SetLogLevelResponse.reason_detail)
+}
+#endif
+inline void SetLogLevelResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.SetLogLevelResponse.reason_detail)
+}
+inline void SetLogLevelResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.SetLogLevelResponse.reason_detail)
+}
+inline ::std::string* SetLogLevelResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.SetLogLevelResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* SetLogLevelResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.SetLogLevelResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void SetLogLevelResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.SetLogLevelResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// GetLogLevelRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool GetLogLevelRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& GetLogLevelRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.GetLogLevelRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* GetLogLevelRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.GetLogLevelRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* GetLogLevelRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.GetLogLevelRequest.device_uuid)
+  return device_uuid_;
+}
+inline void GetLogLevelRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetLogLevelRequest.device_uuid)
+}
+
+// repeated string entities = 2;
+inline int GetLogLevelRequest::entities_size() const {
+  return entities_.size();
+}
+inline void GetLogLevelRequest::clear_entities() {
+  entities_.Clear();
+}
+inline const ::std::string& GetLogLevelRequest::entities(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.GetLogLevelRequest.entities)
+  return entities_.Get(index);
+}
+inline ::std::string* GetLogLevelRequest::mutable_entities(int index) {
+  // @@protoc_insertion_point(field_mutable:dmi.GetLogLevelRequest.entities)
+  return entities_.Mutable(index);
+}
+inline void GetLogLevelRequest::set_entities(int index, const ::std::string& value) {
+  // @@protoc_insertion_point(field_set:dmi.GetLogLevelRequest.entities)
+  entities_.Mutable(index)->assign(value);
+}
+#if LANG_CXX11
+inline void GetLogLevelRequest::set_entities(int index, ::std::string&& value) {
+  // @@protoc_insertion_point(field_set:dmi.GetLogLevelRequest.entities)
+  entities_.Mutable(index)->assign(std::move(value));
+}
+#endif
+inline void GetLogLevelRequest::set_entities(int index, const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  entities_.Mutable(index)->assign(value);
+  // @@protoc_insertion_point(field_set_char:dmi.GetLogLevelRequest.entities)
+}
+inline void GetLogLevelRequest::set_entities(int index, const char* value, size_t size) {
+  entities_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_set_pointer:dmi.GetLogLevelRequest.entities)
+}
+inline ::std::string* GetLogLevelRequest::add_entities() {
+  // @@protoc_insertion_point(field_add_mutable:dmi.GetLogLevelRequest.entities)
+  return entities_.Add();
+}
+inline void GetLogLevelRequest::add_entities(const ::std::string& value) {
+  entities_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add:dmi.GetLogLevelRequest.entities)
+}
+#if LANG_CXX11
+inline void GetLogLevelRequest::add_entities(::std::string&& value) {
+  entities_.Add(std::move(value));
+  // @@protoc_insertion_point(field_add:dmi.GetLogLevelRequest.entities)
+}
+#endif
+inline void GetLogLevelRequest::add_entities(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  entities_.Add()->assign(value);
+  // @@protoc_insertion_point(field_add_char:dmi.GetLogLevelRequest.entities)
+}
+inline void GetLogLevelRequest::add_entities(const char* value, size_t size) {
+  entities_.Add()->assign(reinterpret_cast<const char*>(value), size);
+  // @@protoc_insertion_point(field_add_pointer:dmi.GetLogLevelRequest.entities)
+}
+inline const ::google::protobuf::RepeatedPtrField<::std::string>&
+GetLogLevelRequest::entities() const {
+  // @@protoc_insertion_point(field_list:dmi.GetLogLevelRequest.entities)
+  return entities_;
+}
+inline ::google::protobuf::RepeatedPtrField<::std::string>*
+GetLogLevelRequest::mutable_entities() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.GetLogLevelRequest.entities)
+  return &entities_;
+}
+
+// -------------------------------------------------------------------
+
+// GetLogLevelResponse
+
+// .dmi.Uuid device_uuid = 1;
+inline bool GetLogLevelResponse::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& GetLogLevelResponse::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.GetLogLevelResponse.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* GetLogLevelResponse::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.GetLogLevelResponse.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* GetLogLevelResponse::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.GetLogLevelResponse.device_uuid)
+  return device_uuid_;
+}
+inline void GetLogLevelResponse::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetLogLevelResponse.device_uuid)
+}
+
+// repeated .dmi.EntitiesLogLevel logLevels = 2;
+inline int GetLogLevelResponse::loglevels_size() const {
+  return loglevels_.size();
+}
+inline void GetLogLevelResponse::clear_loglevels() {
+  loglevels_.Clear();
+}
+inline ::dmi::EntitiesLogLevel* GetLogLevelResponse::mutable_loglevels(int index) {
+  // @@protoc_insertion_point(field_mutable:dmi.GetLogLevelResponse.logLevels)
+  return loglevels_.Mutable(index);
+}
+inline ::google::protobuf::RepeatedPtrField< ::dmi::EntitiesLogLevel >*
+GetLogLevelResponse::mutable_loglevels() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.GetLogLevelResponse.logLevels)
+  return &loglevels_;
+}
+inline const ::dmi::EntitiesLogLevel& GetLogLevelResponse::loglevels(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.GetLogLevelResponse.logLevels)
+  return loglevels_.Get(index);
+}
+inline ::dmi::EntitiesLogLevel* GetLogLevelResponse::add_loglevels() {
+  // @@protoc_insertion_point(field_add:dmi.GetLogLevelResponse.logLevels)
+  return loglevels_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::dmi::EntitiesLogLevel >&
+GetLogLevelResponse::loglevels() const {
+  // @@protoc_insertion_point(field_list:dmi.GetLogLevelResponse.logLevels)
+  return loglevels_;
+}
+
+// .dmi.Status status = 3;
+inline void GetLogLevelResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status GetLogLevelResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.GetLogLevelResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void GetLogLevelResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.GetLogLevelResponse.status)
+}
+
+// .dmi.GetLogLevelResponse.Reason reason = 4;
+inline void GetLogLevelResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::GetLogLevelResponse_Reason GetLogLevelResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.GetLogLevelResponse.reason)
+  return static_cast< ::dmi::GetLogLevelResponse_Reason >(reason_);
+}
+inline void GetLogLevelResponse::set_reason(::dmi::GetLogLevelResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.GetLogLevelResponse.reason)
+}
+
+// string reason_detail = 5;
+inline void GetLogLevelResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& GetLogLevelResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.GetLogLevelResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void GetLogLevelResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.GetLogLevelResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void GetLogLevelResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.GetLogLevelResponse.reason_detail)
+}
+#endif
+inline void GetLogLevelResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.GetLogLevelResponse.reason_detail)
+}
+inline void GetLogLevelResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.GetLogLevelResponse.reason_detail)
+}
+inline ::std::string* GetLogLevelResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.GetLogLevelResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* GetLogLevelResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.GetLogLevelResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void GetLogLevelResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetLogLevelResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// GetLoggableEntitiesRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool GetLoggableEntitiesRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& GetLoggableEntitiesRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.GetLoggableEntitiesRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* GetLoggableEntitiesRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.GetLoggableEntitiesRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* GetLoggableEntitiesRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.GetLoggableEntitiesRequest.device_uuid)
+  return device_uuid_;
+}
+inline void GetLoggableEntitiesRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetLoggableEntitiesRequest.device_uuid)
+}
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace dmi
+
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::dmi::PhysicalInventoryResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::PhysicalInventoryResponse_Reason>() {
+  return ::dmi::PhysicalInventoryResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::HWComponentInfoGetResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::HWComponentInfoGetResponse_Reason>() {
+  return ::dmi::HWComponentInfoGetResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::HWComponentInfoSetResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::HWComponentInfoSetResponse_Reason>() {
+  return ::dmi::HWComponentInfoSetResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::StartManagingDeviceResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::StartManagingDeviceResponse_Reason>() {
+  return ::dmi::StartManagingDeviceResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::StopManagingDeviceResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::StopManagingDeviceResponse_Reason>() {
+  return ::dmi::StopManagingDeviceResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::ManagedDevicesResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ManagedDevicesResponse_Reason>() {
+  return ::dmi::ManagedDevicesResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::SetRemoteEndpointResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::SetRemoteEndpointResponse_Reason>() {
+  return ::dmi::SetRemoteEndpointResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::GetLoggingEndpointResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::GetLoggingEndpointResponse_Reason>() {
+  return ::dmi::GetLoggingEndpointResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::GetMsgBusEndpointResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::GetMsgBusEndpointResponse_Reason>() {
+  return ::dmi::GetMsgBusEndpointResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::SetLogLevelResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::SetLogLevelResponse_Reason>() {
+  return ::dmi::SetLogLevelResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::GetLogLevelResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::GetLogLevelResponse_Reason>() {
+  return ::dmi::GetLogLevelResponse_Reason_descriptor();
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#include <google/protobuf/port_undef.inc>
+#endif  // PROTOBUF_INCLUDED_dmi_2fhw_5fmanagement_5fservice_2eproto
diff --git a/cpp/dmi/hw_metrics_mgmt_service.pb.cc b/cpp/dmi/hw_metrics_mgmt_service.pb.cc
new file mode 100644
index 0000000..389e53d
--- /dev/null
+++ b/cpp/dmi/hw_metrics_mgmt_service.pb.cc
@@ -0,0 +1,4155 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/hw_metrics_mgmt_service.proto
+
+#include "dmi/hw_metrics_mgmt_service.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Uuid_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_ComponentSensorData_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<2> scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+namespace dmi {
+class MetricConfigDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<MetricConfig> _instance;
+} _MetricConfig_default_instance_;
+class MetricsConfigDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<MetricsConfig> _instance;
+} _MetricsConfig_default_instance_;
+class ListMetricsResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ListMetricsResponse> _instance;
+} _ListMetricsResponse_default_instance_;
+class MetricsConfigurationRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<MetricsConfigurationRequest> _instance;
+  const ::dmi::MetricsConfig* changes_;
+  bool reset_to_default_;
+} _MetricsConfigurationRequest_default_instance_;
+class MetricsConfigurationResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<MetricsConfigurationResponse> _instance;
+} _MetricsConfigurationResponse_default_instance_;
+class MetricMetaDataDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<MetricMetaData> _instance;
+} _MetricMetaData_default_instance_;
+class MetricDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<Metric> _instance;
+} _Metric_default_instance_;
+class GetMetricRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<GetMetricRequest> _instance;
+} _GetMetricRequest_default_instance_;
+class GetMetricResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<GetMetricResponse> _instance;
+} _GetMetricResponse_default_instance_;
+}  // namespace dmi
+static void InitDefaultsMetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_MetricConfig_default_instance_;
+    new (ptr) ::dmi::MetricConfig();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::MetricConfig::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsMetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {}};
+
+static void InitDefaultsMetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_MetricsConfig_default_instance_;
+    new (ptr) ::dmi::MetricsConfig();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::MetricsConfig::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsMetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ListMetricsResponse_default_instance_;
+    new (ptr) ::dmi::ListMetricsResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ListMetricsResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_ListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsMetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_MetricsConfigurationRequest_default_instance_;
+    new (ptr) ::dmi::MetricsConfigurationRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::MetricsConfigurationRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_MetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsMetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,
+      &scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsMetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_MetricsConfigurationResponse_default_instance_;
+    new (ptr) ::dmi::MetricsConfigurationResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::MetricsConfigurationResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_MetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsMetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {}};
+
+static void InitDefaultsMetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_MetricMetaData_default_instance_;
+    new (ptr) ::dmi::MetricMetaData();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::MetricMetaData::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsMetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsMetric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_Metric_default_instance_;
+    new (ptr) ::dmi::Metric();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::Metric::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsMetric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,
+      &scc_info_ComponentSensorData_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsGetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_GetMetricRequest_default_instance_;
+    new (ptr) ::dmi::GetMetricRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::GetMetricRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_GetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsGetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};
+
+static void InitDefaultsGetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_GetMetricResponse_default_instance_;
+    new (ptr) ::dmi::GetMetricResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::GetMetricResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_GetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsGetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
+      &scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};
+
+void InitDefaults_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  ::google::protobuf::internal::InitSCC(&scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_MetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_MetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_GetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_GetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+}
+
+::google::protobuf::Metadata file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[9];
+const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[4];
+constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = nullptr;
+
+const ::google::protobuf::uint32 TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricConfig, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricConfig, metric_id_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricConfig, is_configured_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricConfig, poll_interval_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfig, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfig, metrics_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, metrics_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationRequest, _oneof_case_[0]),
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationRequest, device_uuid_),
+  offsetof(::dmi::MetricsConfigurationRequestDefaultTypeInternal, changes_),
+  offsetof(::dmi::MetricsConfigurationRequestDefaultTypeInternal, reset_to_default_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationRequest, operation_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricMetaData, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricMetaData, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricMetaData, component_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::MetricMetaData, component_name_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::Metric, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::Metric, metric_id_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Metric, metric_metadata_),
+  PROTOBUF_FIELD_OFFSET(::dmi::Metric, value_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricRequest, meta_data_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricRequest, metric_id_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, metric_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, reason_detail_),
+};
+static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, -1, sizeof(::dmi::MetricConfig)},
+  { 8, -1, sizeof(::dmi::MetricsConfig)},
+  { 14, -1, sizeof(::dmi::ListMetricsResponse)},
+  { 23, -1, sizeof(::dmi::MetricsConfigurationRequest)},
+  { 32, -1, sizeof(::dmi::MetricsConfigurationResponse)},
+  { 40, -1, sizeof(::dmi::MetricMetaData)},
+  { 48, -1, sizeof(::dmi::Metric)},
+  { 56, -1, sizeof(::dmi::GetMetricRequest)},
+  { 63, -1, sizeof(::dmi::GetMetricResponse)},
+};
+
+static ::google::protobuf::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricConfig_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricsConfig_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ListMetricsResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricsConfigurationRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricsConfigurationResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricMetaData_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_Metric_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetMetricRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetMetricResponse_default_instance_),
+};
+
+::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = {
+  {}, AddDescriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, "dmi/hw_metrics_mgmt_service.proto", schemas,
+  file_default_instances, TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto::offsets,
+  file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, 9, file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, file_level_service_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto,
+};
+
+const char descriptor_table_protodef_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[] =
+  "\n!dmi/hw_metrics_mgmt_service.proto\022\003dmi"
+  "\032\021dmi/commons.proto\032\014dmi/hw.proto\"a\n\014Met"
+  "ricConfig\022#\n\tmetric_id\030\001 \001(\0162\020.dmi.Metri"
+  "cNames\022\025\n\ris_configured\030\002 \001(\010\022\025\n\rpoll_in"
+  "terval\030\003 \001(\r\"3\n\rMetricsConfig\022\"\n\007metrics"
+  "\030\001 \003(\0132\021.dmi.MetricConfig\"\377\001\n\023ListMetric"
+  "sResponse\022\033\n\006status\030\001 \001(\0162\013.dmi.Status\022/"
+  "\n\006reason\030\002 \001(\0162\037.dmi.ListMetricsResponse"
+  ".Reason\022#\n\007metrics\030\003 \001(\0132\022.dmi.MetricsCo"
+  "nfig\022\025\n\rreason_detail\030\004 \001(\t\"^\n\006Reason\022\024\n"
+  "\020UNDEFINED_REASON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022"
+  "\022\n\016INTERNAL_ERROR\020\002\022\026\n\022DEVICE_UNREACHABL"
+  "E\020\003\"\215\001\n\033MetricsConfigurationRequest\022\036\n\013d"
+  "evice_uuid\030\001 \001(\0132\t.dmi.Uuid\022%\n\007changes\030\002"
+  " \001(\0132\022.dmi.MetricsConfigH\000\022\032\n\020reset_to_d"
+  "efault\030\003 \001(\010H\000B\013\n\toperation\"\240\002\n\034MetricsC"
+  "onfigurationResponse\022\033\n\006status\030\001 \001(\0162\013.d"
+  "mi.Status\0228\n\006reason\030\002 \001(\0162(.dmi.MetricsC"
+  "onfigurationResponse.Reason\022\025\n\rreason_de"
+  "tail\030\003 \001(\t\"\221\001\n\006Reason\022\024\n\020UNDEFINED_REASO"
+  "N\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERNAL_ERRO"
+  "R\020\002\022\035\n\031POLL_INTERVAL_UNSUPPORTED\020\003\022\022\n\016IN"
+  "VALID_METRIC\020\004\022\026\n\022DEVICE_UNREACHABLE\020\005\"k"
+  "\n\016MetricMetaData\022\036\n\013device_uuid\030\001 \001(\0132\t."
+  "dmi.Uuid\022!\n\016component_uuid\030\002 \001(\0132\t.dmi.U"
+  "uid\022\026\n\016component_name\030\003 \001(\t\"\204\001\n\006Metric\022#"
+  "\n\tmetric_id\030\001 \001(\0162\020.dmi.MetricNames\022,\n\017m"
+  "etric_metadata\030\002 \001(\0132\023.dmi.MetricMetaDat"
+  "a\022\'\n\005value\030\003 \001(\0132\030.dmi.ComponentSensorDa"
+  "ta\"_\n\020GetMetricRequest\022&\n\tmeta_data\030\001 \001("
+  "\0132\023.dmi.MetricMetaData\022#\n\tmetric_id\030\002 \001("
+  "\0162\020.dmi.MetricNames\"\237\002\n\021GetMetricRespons"
+  "e\022\033\n\006status\030\001 \001(\0162\013.dmi.Status\022-\n\006reason"
+  "\030\002 \001(\0162\035.dmi.GetMetricResponse.Reason\022\033\n"
+  "\006metric\030\003 \001(\0132\013.dmi.Metric\022\025\n\rreason_det"
+  "ail\030\004 \001(\t\"\211\001\n\006Reason\022\024\n\020UNDEFINED_REASON"
+  "\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\025\n\021UNKNOWN_COMPON"
+  "ENT\020\002\022\022\n\016INTERNAL_ERROR\020\003\022\022\n\016INVALID_MET"
+  "RIC\020\004\022\026\n\022DEVICE_UNREACHABLE\020\005*\331\005\n\013Metric"
+  "Names\022\031\n\025METRIC_NAME_UNDEFINED\020\000\022\024\n\020METR"
+  "IC_FAN_SPEED\020\001\022\023\n\017METRIC_CPU_TEMP\020d\022\037\n\033M"
+  "ETRIC_CPU_USAGE_PERCENTAGE\020e\022\034\n\027METRIC_T"
+  "RANSCEIVER_TEMP\020\310\001\022\037\n\032METRIC_TRANSCEIVER"
+  "_VOLTAGE\020\311\001\022\034\n\027METRIC_TRANSCEIVER_BIAS\020\312"
+  "\001\022 \n\033METRIC_TRANSCEIVER_RX_POWER\020\313\001\022 \n\033M"
+  "ETRIC_TRANSCEIVER_TX_POWER\020\314\001\022\"\n\035METRIC_"
+  "TRANSCEIVER_WAVELENGTH\020\315\001\022\025\n\020METRIC_DISK"
+  "_TEMP\020\254\002\022\031\n\024METRIC_DISK_CAPACITY\020\255\002\022\026\n\021M"
+  "ETRIC_DISK_USAGE\020\256\002\022!\n\034METRIC_DISK_USAGE"
+  "_PERCENTAGE\020\257\002\022&\n!METRIC_DISK_READ_WRITE"
+  "_PERCENTAGE\020\260\002\022(\n#METRIC_DISK_FAULTY_CEL"
+  "LS_PERCENTAGE\020\261\002\022\024\n\017METRIC_RAM_TEMP\020\220\003\022\030"
+  "\n\023METRIC_RAM_CAPACITY\020\221\003\022\025\n\020METRIC_RAM_U"
+  "SAGE\020\222\003\022 \n\033METRIC_RAM_USAGE_PERCENTAGE\020\223"
+  "\003\022\025\n\020METRIC_POWER_MAX\020\364\003\022\027\n\022METRIC_POWER"
+  "_USAGE\020\365\003\022\"\n\035METRIC_POWER_USAGE_PERCENTA"
+  "GE\020\366\003\022\"\n\035METRIC_INNER_SURROUNDING_TEMP\020\330"
+  "\0042\371\001\n\036NativeMetricsManagementService\0228\n\013"
+  "ListMetrics\022\017.dmi.HardwareID\032\030.dmi.ListM"
+  "etricsResponse\022a\n\032UpdateMetricsConfigura"
+  "tion\022 .dmi.MetricsConfigurationRequest\032!"
+  ".dmi.MetricsConfigurationResponse\022:\n\tGet"
+  "Metric\022\025.dmi.GetMetricRequest\032\026.dmi.GetM"
+  "etricResponseB;Z9github.com/opencord/dev"
+  "ice-management-interface/v3/go/dmib\006prot"
+  "o3"
+  ;
+::google::protobuf::internal::DescriptorTable descriptor_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = {
+  false, InitDefaults_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, 
+  descriptor_table_protodef_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto,
+  "dmi/hw_metrics_mgmt_service.proto", &assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, 2602,
+};
+
+void AddDescriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
+  static constexpr ::google::protobuf::internal::InitFunc deps[2] =
+  {
+    ::AddDescriptors_dmi_2fcommons_2eproto,
+    ::AddDescriptors_dmi_2fhw_2eproto,
+  };
+ ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, deps, 2);
+}
+
+// Force running AddDescriptors() at dynamic initialization time.
+static bool dynamic_init_dummy_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = []() { AddDescriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto(); return true; }();
+namespace dmi {
+const ::google::protobuf::EnumDescriptor* ListMetricsResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[0];
+}
+bool ListMetricsResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const ListMetricsResponse_Reason ListMetricsResponse::UNDEFINED_REASON;
+const ListMetricsResponse_Reason ListMetricsResponse::UNKNOWN_DEVICE;
+const ListMetricsResponse_Reason ListMetricsResponse::INTERNAL_ERROR;
+const ListMetricsResponse_Reason ListMetricsResponse::DEVICE_UNREACHABLE;
+const ListMetricsResponse_Reason ListMetricsResponse::Reason_MIN;
+const ListMetricsResponse_Reason ListMetricsResponse::Reason_MAX;
+const int ListMetricsResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* MetricsConfigurationResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[1];
+}
+bool MetricsConfigurationResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::UNDEFINED_REASON;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::UNKNOWN_DEVICE;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::INTERNAL_ERROR;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::POLL_INTERVAL_UNSUPPORTED;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::INVALID_METRIC;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::DEVICE_UNREACHABLE;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::Reason_MIN;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::Reason_MAX;
+const int MetricsConfigurationResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* GetMetricResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[2];
+}
+bool GetMetricResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const GetMetricResponse_Reason GetMetricResponse::UNDEFINED_REASON;
+const GetMetricResponse_Reason GetMetricResponse::UNKNOWN_DEVICE;
+const GetMetricResponse_Reason GetMetricResponse::UNKNOWN_COMPONENT;
+const GetMetricResponse_Reason GetMetricResponse::INTERNAL_ERROR;
+const GetMetricResponse_Reason GetMetricResponse::INVALID_METRIC;
+const GetMetricResponse_Reason GetMetricResponse::DEVICE_UNREACHABLE;
+const GetMetricResponse_Reason GetMetricResponse::Reason_MIN;
+const GetMetricResponse_Reason GetMetricResponse::Reason_MAX;
+const int GetMetricResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* MetricNames_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[3];
+}
+bool MetricNames_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 100:
+    case 101:
+    case 200:
+    case 201:
+    case 202:
+    case 203:
+    case 204:
+    case 205:
+    case 300:
+    case 301:
+    case 302:
+    case 303:
+    case 304:
+    case 305:
+    case 400:
+    case 401:
+    case 402:
+    case 403:
+    case 500:
+    case 501:
+    case 502:
+    case 600:
+      return true;
+    default:
+      return false;
+  }
+}
+
+
+// ===================================================================
+
+void MetricConfig::InitAsDefaultInstance() {
+}
+class MetricConfig::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MetricConfig::kMetricIdFieldNumber;
+const int MetricConfig::kIsConfiguredFieldNumber;
+const int MetricConfig::kPollIntervalFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MetricConfig::MetricConfig()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.MetricConfig)
+}
+MetricConfig::MetricConfig(const MetricConfig& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::memcpy(&metric_id_, &from.metric_id_,
+    static_cast<size_t>(reinterpret_cast<char*>(&poll_interval_) -
+    reinterpret_cast<char*>(&metric_id_)) + sizeof(poll_interval_));
+  // @@protoc_insertion_point(copy_constructor:dmi.MetricConfig)
+}
+
+void MetricConfig::SharedCtor() {
+  ::memset(&metric_id_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&poll_interval_) -
+      reinterpret_cast<char*>(&metric_id_)) + sizeof(poll_interval_));
+}
+
+MetricConfig::~MetricConfig() {
+  // @@protoc_insertion_point(destructor:dmi.MetricConfig)
+  SharedDtor();
+}
+
+void MetricConfig::SharedDtor() {
+}
+
+void MetricConfig::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const MetricConfig& MetricConfig::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void MetricConfig::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.MetricConfig)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  ::memset(&metric_id_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&poll_interval_) -
+      reinterpret_cast<char*>(&metric_id_)) + sizeof(poll_interval_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* MetricConfig::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<MetricConfig*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.MetricNames metric_id = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_metric_id(static_cast<::dmi::MetricNames>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // bool is_configured = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        msg->set_is_configured(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // uint32 poll_interval = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
+        msg->set_poll_interval(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool MetricConfig::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.MetricConfig)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.MetricNames metric_id = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_metric_id(static_cast< ::dmi::MetricNames >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // bool is_configured = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &is_configured_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // uint32 poll_interval = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
+
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
+                 input, &poll_interval_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.MetricConfig)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.MetricConfig)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void MetricConfig::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.MetricConfig)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.MetricNames metric_id = 1;
+  if (this->metric_id() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->metric_id(), output);
+  }
+
+  // bool is_configured = 2;
+  if (this->is_configured() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_configured(), output);
+  }
+
+  // uint32 poll_interval = 3;
+  if (this->poll_interval() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(3, this->poll_interval(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.MetricConfig)
+}
+
+::google::protobuf::uint8* MetricConfig::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricConfig)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.MetricNames metric_id = 1;
+  if (this->metric_id() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->metric_id(), target);
+  }
+
+  // bool is_configured = 2;
+  if (this->is_configured() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_configured(), target);
+  }
+
+  // uint32 poll_interval = 3;
+  if (this->poll_interval() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(3, this->poll_interval(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricConfig)
+  return target;
+}
+
+size_t MetricConfig::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.MetricConfig)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.MetricNames metric_id = 1;
+  if (this->metric_id() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->metric_id());
+  }
+
+  // bool is_configured = 2;
+  if (this->is_configured() != 0) {
+    total_size += 1 + 1;
+  }
+
+  // uint32 poll_interval = 3;
+  if (this->poll_interval() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::UInt32Size(
+        this->poll_interval());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void MetricConfig::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricConfig)
+  GOOGLE_DCHECK_NE(&from, this);
+  const MetricConfig* source =
+      ::google::protobuf::DynamicCastToGenerated<MetricConfig>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricConfig)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricConfig)
+    MergeFrom(*source);
+  }
+}
+
+void MetricConfig::MergeFrom(const MetricConfig& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricConfig)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.metric_id() != 0) {
+    set_metric_id(from.metric_id());
+  }
+  if (from.is_configured() != 0) {
+    set_is_configured(from.is_configured());
+  }
+  if (from.poll_interval() != 0) {
+    set_poll_interval(from.poll_interval());
+  }
+}
+
+void MetricConfig::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricConfig)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MetricConfig::CopyFrom(const MetricConfig& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricConfig)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MetricConfig::IsInitialized() const {
+  return true;
+}
+
+void MetricConfig::Swap(MetricConfig* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MetricConfig::InternalSwap(MetricConfig* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(metric_id_, other->metric_id_);
+  swap(is_configured_, other->is_configured_);
+  swap(poll_interval_, other->poll_interval_);
+}
+
+::google::protobuf::Metadata MetricConfig::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void MetricsConfig::InitAsDefaultInstance() {
+}
+class MetricsConfig::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MetricsConfig::kMetricsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MetricsConfig::MetricsConfig()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.MetricsConfig)
+}
+MetricsConfig::MetricsConfig(const MetricsConfig& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr),
+      metrics_(from.metrics_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  // @@protoc_insertion_point(copy_constructor:dmi.MetricsConfig)
+}
+
+void MetricsConfig::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+}
+
+MetricsConfig::~MetricsConfig() {
+  // @@protoc_insertion_point(destructor:dmi.MetricsConfig)
+  SharedDtor();
+}
+
+void MetricsConfig::SharedDtor() {
+}
+
+void MetricsConfig::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const MetricsConfig& MetricsConfig::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void MetricsConfig::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.MetricsConfig)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  metrics_.Clear();
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* MetricsConfig::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<MetricsConfig*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // repeated .dmi.MetricConfig metrics = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        do {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          parser_till_end = ::dmi::MetricConfig::_InternalParse;
+          object = msg->add_metrics();
+          if (size > end - ptr) goto len_delim_till_end;
+          ptr += size;
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+              {parser_till_end, object}, ptr - size, ptr));
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 10 && (ptr += 1));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool MetricsConfig::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.MetricsConfig)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .dmi.MetricConfig metrics = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+                input, add_metrics()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.MetricsConfig)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.MetricsConfig)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void MetricsConfig::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.MetricsConfig)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // repeated .dmi.MetricConfig metrics = 1;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->metrics_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1,
+      this->metrics(static_cast<int>(i)),
+      output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.MetricsConfig)
+}
+
+::google::protobuf::uint8* MetricsConfig::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricsConfig)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // repeated .dmi.MetricConfig metrics = 1;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->metrics_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, this->metrics(static_cast<int>(i)), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricsConfig)
+  return target;
+}
+
+size_t MetricsConfig::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.MetricsConfig)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated .dmi.MetricConfig metrics = 1;
+  {
+    unsigned int count = static_cast<unsigned int>(this->metrics_size());
+    total_size += 1UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->metrics(static_cast<int>(i)));
+    }
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void MetricsConfig::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricsConfig)
+  GOOGLE_DCHECK_NE(&from, this);
+  const MetricsConfig* source =
+      ::google::protobuf::DynamicCastToGenerated<MetricsConfig>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricsConfig)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricsConfig)
+    MergeFrom(*source);
+  }
+}
+
+void MetricsConfig::MergeFrom(const MetricsConfig& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricsConfig)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  metrics_.MergeFrom(from.metrics_);
+}
+
+void MetricsConfig::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricsConfig)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MetricsConfig::CopyFrom(const MetricsConfig& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricsConfig)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MetricsConfig::IsInitialized() const {
+  return true;
+}
+
+void MetricsConfig::Swap(MetricsConfig* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MetricsConfig::InternalSwap(MetricsConfig* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  CastToBase(&metrics_)->InternalSwap(CastToBase(&other->metrics_));
+}
+
+::google::protobuf::Metadata MetricsConfig::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ListMetricsResponse::InitAsDefaultInstance() {
+  ::dmi::_ListMetricsResponse_default_instance_._instance.get_mutable()->metrics_ = const_cast< ::dmi::MetricsConfig*>(
+      ::dmi::MetricsConfig::internal_default_instance());
+}
+class ListMetricsResponse::HasBitSetters {
+ public:
+  static const ::dmi::MetricsConfig& metrics(const ListMetricsResponse* msg);
+};
+
+const ::dmi::MetricsConfig&
+ListMetricsResponse::HasBitSetters::metrics(const ListMetricsResponse* msg) {
+  return *msg->metrics_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ListMetricsResponse::kStatusFieldNumber;
+const int ListMetricsResponse::kReasonFieldNumber;
+const int ListMetricsResponse::kMetricsFieldNumber;
+const int ListMetricsResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ListMetricsResponse::ListMetricsResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ListMetricsResponse)
+}
+ListMetricsResponse::ListMetricsResponse(const ListMetricsResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_metrics()) {
+    metrics_ = new ::dmi::MetricsConfig(*from.metrics_);
+  } else {
+    metrics_ = nullptr;
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.ListMetricsResponse)
+}
+
+void ListMetricsResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&metrics_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&metrics_)) + sizeof(reason_));
+}
+
+ListMetricsResponse::~ListMetricsResponse() {
+  // @@protoc_insertion_point(destructor:dmi.ListMetricsResponse)
+  SharedDtor();
+}
+
+void ListMetricsResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete metrics_;
+}
+
+void ListMetricsResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ListMetricsResponse& ListMetricsResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ListMetricsResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ListMetricsResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && metrics_ != nullptr) {
+    delete metrics_;
+  }
+  metrics_ = nullptr;
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ListMetricsResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ListMetricsResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ListMetricsResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::ListMetricsResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.MetricsConfig metrics = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::MetricsConfig::_InternalParse;
+        object = msg->mutable_metrics();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ListMetricsResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ListMetricsResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ListMetricsResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ListMetricsResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::ListMetricsResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.MetricsConfig metrics = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_metrics()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ListMetricsResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ListMetricsResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ListMetricsResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ListMetricsResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ListMetricsResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.ListMetricsResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // .dmi.MetricsConfig metrics = 3;
+  if (this->has_metrics()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::metrics(this), output);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ListMetricsResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ListMetricsResponse)
+}
+
+::google::protobuf::uint8* ListMetricsResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ListMetricsResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.ListMetricsResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // .dmi.MetricsConfig metrics = 3;
+  if (this->has_metrics()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::metrics(this), target);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ListMetricsResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ListMetricsResponse)
+  return target;
+}
+
+size_t ListMetricsResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ListMetricsResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.MetricsConfig metrics = 3;
+  if (this->has_metrics()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *metrics_);
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.ListMetricsResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ListMetricsResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ListMetricsResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ListMetricsResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<ListMetricsResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ListMetricsResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ListMetricsResponse)
+    MergeFrom(*source);
+  }
+}
+
+void ListMetricsResponse::MergeFrom(const ListMetricsResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ListMetricsResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_metrics()) {
+    mutable_metrics()->::dmi::MetricsConfig::MergeFrom(from.metrics());
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void ListMetricsResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ListMetricsResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ListMetricsResponse::CopyFrom(const ListMetricsResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ListMetricsResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ListMetricsResponse::IsInitialized() const {
+  return true;
+}
+
+void ListMetricsResponse::Swap(ListMetricsResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ListMetricsResponse::InternalSwap(ListMetricsResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(metrics_, other->metrics_);
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata ListMetricsResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void MetricsConfigurationRequest::InitAsDefaultInstance() {
+  ::dmi::_MetricsConfigurationRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+  ::dmi::_MetricsConfigurationRequest_default_instance_.changes_ = const_cast< ::dmi::MetricsConfig*>(
+      ::dmi::MetricsConfig::internal_default_instance());
+  ::dmi::_MetricsConfigurationRequest_default_instance_.reset_to_default_ = false;
+}
+class MetricsConfigurationRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const MetricsConfigurationRequest* msg);
+  static const ::dmi::MetricsConfig& changes(const MetricsConfigurationRequest* msg);
+};
+
+const ::dmi::Uuid&
+MetricsConfigurationRequest::HasBitSetters::device_uuid(const MetricsConfigurationRequest* msg) {
+  return *msg->device_uuid_;
+}
+const ::dmi::MetricsConfig&
+MetricsConfigurationRequest::HasBitSetters::changes(const MetricsConfigurationRequest* msg) {
+  return *msg->operation_.changes_;
+}
+void MetricsConfigurationRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+void MetricsConfigurationRequest::set_allocated_changes(::dmi::MetricsConfig* changes) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  clear_operation();
+  if (changes) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      changes = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, changes, submessage_arena);
+    }
+    set_has_changes();
+    operation_.changes_ = changes;
+  }
+  // @@protoc_insertion_point(field_set_allocated:dmi.MetricsConfigurationRequest.changes)
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MetricsConfigurationRequest::kDeviceUuidFieldNumber;
+const int MetricsConfigurationRequest::kChangesFieldNumber;
+const int MetricsConfigurationRequest::kResetToDefaultFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MetricsConfigurationRequest::MetricsConfigurationRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.MetricsConfigurationRequest)
+}
+MetricsConfigurationRequest::MetricsConfigurationRequest(const MetricsConfigurationRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  clear_has_operation();
+  switch (from.operation_case()) {
+    case kChanges: {
+      mutable_changes()->::dmi::MetricsConfig::MergeFrom(from.changes());
+      break;
+    }
+    case kResetToDefault: {
+      set_reset_to_default(from.reset_to_default());
+      break;
+    }
+    case OPERATION_NOT_SET: {
+      break;
+    }
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.MetricsConfigurationRequest)
+}
+
+void MetricsConfigurationRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_MetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  device_uuid_ = nullptr;
+  clear_has_operation();
+}
+
+MetricsConfigurationRequest::~MetricsConfigurationRequest() {
+  // @@protoc_insertion_point(destructor:dmi.MetricsConfigurationRequest)
+  SharedDtor();
+}
+
+void MetricsConfigurationRequest::SharedDtor() {
+  if (this != internal_default_instance()) delete device_uuid_;
+  if (has_operation()) {
+    clear_operation();
+  }
+}
+
+void MetricsConfigurationRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const MetricsConfigurationRequest& MetricsConfigurationRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_MetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void MetricsConfigurationRequest::clear_operation() {
+// @@protoc_insertion_point(one_of_clear_start:dmi.MetricsConfigurationRequest)
+  switch (operation_case()) {
+    case kChanges: {
+      delete operation_.changes_;
+      break;
+    }
+    case kResetToDefault: {
+      // No need to clear
+      break;
+    }
+    case OPERATION_NOT_SET: {
+      break;
+    }
+  }
+  _oneof_case_[0] = OPERATION_NOT_SET;
+}
+
+
+void MetricsConfigurationRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.MetricsConfigurationRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  clear_operation();
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* MetricsConfigurationRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<MetricsConfigurationRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.MetricsConfig changes = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::MetricsConfig::_InternalParse;
+        object = msg->mutable_changes();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // bool reset_to_default = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
+        msg->set_reset_to_default(::google::protobuf::internal::ReadVarint(&ptr));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool MetricsConfigurationRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.MetricsConfigurationRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.MetricsConfig changes = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_changes()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // bool reset_to_default = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
+          clear_operation();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &operation_.reset_to_default_)));
+          set_has_reset_to_default();
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.MetricsConfigurationRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.MetricsConfigurationRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void MetricsConfigurationRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.MetricsConfigurationRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // .dmi.MetricsConfig changes = 2;
+  if (has_changes()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::changes(this), output);
+  }
+
+  // bool reset_to_default = 3;
+  if (has_reset_to_default()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->reset_to_default(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.MetricsConfigurationRequest)
+}
+
+::google::protobuf::uint8* MetricsConfigurationRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricsConfigurationRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // .dmi.MetricsConfig changes = 2;
+  if (has_changes()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::changes(this), target);
+  }
+
+  // bool reset_to_default = 3;
+  if (has_reset_to_default()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->reset_to_default(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricsConfigurationRequest)
+  return target;
+}
+
+size_t MetricsConfigurationRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.MetricsConfigurationRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  switch (operation_case()) {
+    // .dmi.MetricsConfig changes = 2;
+    case kChanges: {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          *operation_.changes_);
+      break;
+    }
+    // bool reset_to_default = 3;
+    case kResetToDefault: {
+      total_size += 1 + 1;
+      break;
+    }
+    case OPERATION_NOT_SET: {
+      break;
+    }
+  }
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void MetricsConfigurationRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricsConfigurationRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const MetricsConfigurationRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<MetricsConfigurationRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricsConfigurationRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricsConfigurationRequest)
+    MergeFrom(*source);
+  }
+}
+
+void MetricsConfigurationRequest::MergeFrom(const MetricsConfigurationRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricsConfigurationRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+  switch (from.operation_case()) {
+    case kChanges: {
+      mutable_changes()->::dmi::MetricsConfig::MergeFrom(from.changes());
+      break;
+    }
+    case kResetToDefault: {
+      set_reset_to_default(from.reset_to_default());
+      break;
+    }
+    case OPERATION_NOT_SET: {
+      break;
+    }
+  }
+}
+
+void MetricsConfigurationRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricsConfigurationRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MetricsConfigurationRequest::CopyFrom(const MetricsConfigurationRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricsConfigurationRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MetricsConfigurationRequest::IsInitialized() const {
+  return true;
+}
+
+void MetricsConfigurationRequest::Swap(MetricsConfigurationRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MetricsConfigurationRequest::InternalSwap(MetricsConfigurationRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(device_uuid_, other->device_uuid_);
+  swap(operation_, other->operation_);
+  swap(_oneof_case_[0], other->_oneof_case_[0]);
+}
+
+::google::protobuf::Metadata MetricsConfigurationRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void MetricsConfigurationResponse::InitAsDefaultInstance() {
+}
+class MetricsConfigurationResponse::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MetricsConfigurationResponse::kStatusFieldNumber;
+const int MetricsConfigurationResponse::kReasonFieldNumber;
+const int MetricsConfigurationResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MetricsConfigurationResponse::MetricsConfigurationResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.MetricsConfigurationResponse)
+}
+MetricsConfigurationResponse::MetricsConfigurationResponse(const MetricsConfigurationResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.MetricsConfigurationResponse)
+}
+
+void MetricsConfigurationResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_MetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+}
+
+MetricsConfigurationResponse::~MetricsConfigurationResponse() {
+  // @@protoc_insertion_point(destructor:dmi.MetricsConfigurationResponse)
+  SharedDtor();
+}
+
+void MetricsConfigurationResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void MetricsConfigurationResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const MetricsConfigurationResponse& MetricsConfigurationResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_MetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void MetricsConfigurationResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.MetricsConfigurationResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* MetricsConfigurationResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<MetricsConfigurationResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.MetricsConfigurationResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::MetricsConfigurationResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.MetricsConfigurationResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool MetricsConfigurationResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.MetricsConfigurationResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.MetricsConfigurationResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::MetricsConfigurationResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.MetricsConfigurationResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.MetricsConfigurationResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.MetricsConfigurationResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void MetricsConfigurationResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.MetricsConfigurationResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.MetricsConfigurationResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.MetricsConfigurationResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.MetricsConfigurationResponse)
+}
+
+::google::protobuf::uint8* MetricsConfigurationResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricsConfigurationResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.MetricsConfigurationResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.MetricsConfigurationResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricsConfigurationResponse)
+  return target;
+}
+
+size_t MetricsConfigurationResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.MetricsConfigurationResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.MetricsConfigurationResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void MetricsConfigurationResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricsConfigurationResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const MetricsConfigurationResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<MetricsConfigurationResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricsConfigurationResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricsConfigurationResponse)
+    MergeFrom(*source);
+  }
+}
+
+void MetricsConfigurationResponse::MergeFrom(const MetricsConfigurationResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricsConfigurationResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void MetricsConfigurationResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricsConfigurationResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MetricsConfigurationResponse::CopyFrom(const MetricsConfigurationResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricsConfigurationResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MetricsConfigurationResponse::IsInitialized() const {
+  return true;
+}
+
+void MetricsConfigurationResponse::Swap(MetricsConfigurationResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MetricsConfigurationResponse::InternalSwap(MetricsConfigurationResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata MetricsConfigurationResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void MetricMetaData::InitAsDefaultInstance() {
+  ::dmi::_MetricMetaData_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+  ::dmi::_MetricMetaData_default_instance_._instance.get_mutable()->component_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class MetricMetaData::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const MetricMetaData* msg);
+  static const ::dmi::Uuid& component_uuid(const MetricMetaData* msg);
+};
+
+const ::dmi::Uuid&
+MetricMetaData::HasBitSetters::device_uuid(const MetricMetaData* msg) {
+  return *msg->device_uuid_;
+}
+const ::dmi::Uuid&
+MetricMetaData::HasBitSetters::component_uuid(const MetricMetaData* msg) {
+  return *msg->component_uuid_;
+}
+void MetricMetaData::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+void MetricMetaData::clear_component_uuid() {
+  if (GetArenaNoVirtual() == nullptr && component_uuid_ != nullptr) {
+    delete component_uuid_;
+  }
+  component_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int MetricMetaData::kDeviceUuidFieldNumber;
+const int MetricMetaData::kComponentUuidFieldNumber;
+const int MetricMetaData::kComponentNameFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+MetricMetaData::MetricMetaData()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.MetricMetaData)
+}
+MetricMetaData::MetricMetaData(const MetricMetaData& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  component_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.component_name().size() > 0) {
+    component_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.component_name_);
+  }
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  if (from.has_component_uuid()) {
+    component_uuid_ = new ::dmi::Uuid(*from.component_uuid_);
+  } else {
+    component_uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.MetricMetaData)
+}
+
+void MetricMetaData::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  component_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&device_uuid_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&component_uuid_) -
+      reinterpret_cast<char*>(&device_uuid_)) + sizeof(component_uuid_));
+}
+
+MetricMetaData::~MetricMetaData() {
+  // @@protoc_insertion_point(destructor:dmi.MetricMetaData)
+  SharedDtor();
+}
+
+void MetricMetaData::SharedDtor() {
+  component_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete device_uuid_;
+  if (this != internal_default_instance()) delete component_uuid_;
+}
+
+void MetricMetaData::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const MetricMetaData& MetricMetaData::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void MetricMetaData::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.MetricMetaData)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  component_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && component_uuid_ != nullptr) {
+    delete component_uuid_;
+  }
+  component_uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* MetricMetaData::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<MetricMetaData*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.Uuid component_uuid = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_component_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string component_name = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.MetricMetaData.component_name");
+        object = msg->mutable_component_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool MetricMetaData::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.MetricMetaData)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Uuid component_uuid = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_component_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string component_name = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_component_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->component_name().data(), static_cast<int>(this->component_name().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.MetricMetaData.component_name"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.MetricMetaData)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.MetricMetaData)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void MetricMetaData::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.MetricMetaData)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::component_uuid(this), output);
+  }
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->component_name().data(), static_cast<int>(this->component_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.MetricMetaData.component_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->component_name(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.MetricMetaData)
+}
+
+::google::protobuf::uint8* MetricMetaData::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricMetaData)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::component_uuid(this), target);
+  }
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->component_name().data(), static_cast<int>(this->component_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.MetricMetaData.component_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->component_name(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricMetaData)
+  return target;
+}
+
+size_t MetricMetaData::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.MetricMetaData)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string component_name = 3;
+  if (this->component_name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->component_name());
+  }
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  // .dmi.Uuid component_uuid = 2;
+  if (this->has_component_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *component_uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void MetricMetaData::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricMetaData)
+  GOOGLE_DCHECK_NE(&from, this);
+  const MetricMetaData* source =
+      ::google::protobuf::DynamicCastToGenerated<MetricMetaData>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricMetaData)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricMetaData)
+    MergeFrom(*source);
+  }
+}
+
+void MetricMetaData::MergeFrom(const MetricMetaData& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricMetaData)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.component_name().size() > 0) {
+
+    component_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.component_name_);
+  }
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+  if (from.has_component_uuid()) {
+    mutable_component_uuid()->::dmi::Uuid::MergeFrom(from.component_uuid());
+  }
+}
+
+void MetricMetaData::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricMetaData)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MetricMetaData::CopyFrom(const MetricMetaData& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricMetaData)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool MetricMetaData::IsInitialized() const {
+  return true;
+}
+
+void MetricMetaData::Swap(MetricMetaData* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void MetricMetaData::InternalSwap(MetricMetaData* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  component_name_.Swap(&other->component_name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(device_uuid_, other->device_uuid_);
+  swap(component_uuid_, other->component_uuid_);
+}
+
+::google::protobuf::Metadata MetricMetaData::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void Metric::InitAsDefaultInstance() {
+  ::dmi::_Metric_default_instance_._instance.get_mutable()->metric_metadata_ = const_cast< ::dmi::MetricMetaData*>(
+      ::dmi::MetricMetaData::internal_default_instance());
+  ::dmi::_Metric_default_instance_._instance.get_mutable()->value_ = const_cast< ::dmi::ComponentSensorData*>(
+      ::dmi::ComponentSensorData::internal_default_instance());
+}
+class Metric::HasBitSetters {
+ public:
+  static const ::dmi::MetricMetaData& metric_metadata(const Metric* msg);
+  static const ::dmi::ComponentSensorData& value(const Metric* msg);
+};
+
+const ::dmi::MetricMetaData&
+Metric::HasBitSetters::metric_metadata(const Metric* msg) {
+  return *msg->metric_metadata_;
+}
+const ::dmi::ComponentSensorData&
+Metric::HasBitSetters::value(const Metric* msg) {
+  return *msg->value_;
+}
+void Metric::clear_value() {
+  if (GetArenaNoVirtual() == nullptr && value_ != nullptr) {
+    delete value_;
+  }
+  value_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int Metric::kMetricIdFieldNumber;
+const int Metric::kMetricMetadataFieldNumber;
+const int Metric::kValueFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+Metric::Metric()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.Metric)
+}
+Metric::Metric(const Metric& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_metric_metadata()) {
+    metric_metadata_ = new ::dmi::MetricMetaData(*from.metric_metadata_);
+  } else {
+    metric_metadata_ = nullptr;
+  }
+  if (from.has_value()) {
+    value_ = new ::dmi::ComponentSensorData(*from.value_);
+  } else {
+    value_ = nullptr;
+  }
+  metric_id_ = from.metric_id_;
+  // @@protoc_insertion_point(copy_constructor:dmi.Metric)
+}
+
+void Metric::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::memset(&metric_metadata_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&metric_id_) -
+      reinterpret_cast<char*>(&metric_metadata_)) + sizeof(metric_id_));
+}
+
+Metric::~Metric() {
+  // @@protoc_insertion_point(destructor:dmi.Metric)
+  SharedDtor();
+}
+
+void Metric::SharedDtor() {
+  if (this != internal_default_instance()) delete metric_metadata_;
+  if (this != internal_default_instance()) delete value_;
+}
+
+void Metric::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const Metric& Metric::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void Metric::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.Metric)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && metric_metadata_ != nullptr) {
+    delete metric_metadata_;
+  }
+  metric_metadata_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && value_ != nullptr) {
+    delete value_;
+  }
+  value_ = nullptr;
+  metric_id_ = 0;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* Metric::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<Metric*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.MetricNames metric_id = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_metric_id(static_cast<::dmi::MetricNames>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.MetricMetaData metric_metadata = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::MetricMetaData::_InternalParse;
+        object = msg->mutable_metric_metadata();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.ComponentSensorData value = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::ComponentSensorData::_InternalParse;
+        object = msg->mutable_value();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool Metric::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.Metric)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.MetricNames metric_id = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_metric_id(static_cast< ::dmi::MetricNames >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.MetricMetaData metric_metadata = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_metric_metadata()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ComponentSensorData value = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_value()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.Metric)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.Metric)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void Metric::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.Metric)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.MetricNames metric_id = 1;
+  if (this->metric_id() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->metric_id(), output);
+  }
+
+  // .dmi.MetricMetaData metric_metadata = 2;
+  if (this->has_metric_metadata()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::metric_metadata(this), output);
+  }
+
+  // .dmi.ComponentSensorData value = 3;
+  if (this->has_value()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::value(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.Metric)
+}
+
+::google::protobuf::uint8* Metric::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.Metric)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.MetricNames metric_id = 1;
+  if (this->metric_id() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->metric_id(), target);
+  }
+
+  // .dmi.MetricMetaData metric_metadata = 2;
+  if (this->has_metric_metadata()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::metric_metadata(this), target);
+  }
+
+  // .dmi.ComponentSensorData value = 3;
+  if (this->has_value()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::value(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.Metric)
+  return target;
+}
+
+size_t Metric::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.Metric)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.MetricMetaData metric_metadata = 2;
+  if (this->has_metric_metadata()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *metric_metadata_);
+  }
+
+  // .dmi.ComponentSensorData value = 3;
+  if (this->has_value()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *value_);
+  }
+
+  // .dmi.MetricNames metric_id = 1;
+  if (this->metric_id() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->metric_id());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void Metric::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.Metric)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Metric* source =
+      ::google::protobuf::DynamicCastToGenerated<Metric>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.Metric)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.Metric)
+    MergeFrom(*source);
+  }
+}
+
+void Metric::MergeFrom(const Metric& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.Metric)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_metric_metadata()) {
+    mutable_metric_metadata()->::dmi::MetricMetaData::MergeFrom(from.metric_metadata());
+  }
+  if (from.has_value()) {
+    mutable_value()->::dmi::ComponentSensorData::MergeFrom(from.value());
+  }
+  if (from.metric_id() != 0) {
+    set_metric_id(from.metric_id());
+  }
+}
+
+void Metric::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.Metric)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Metric::CopyFrom(const Metric& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.Metric)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Metric::IsInitialized() const {
+  return true;
+}
+
+void Metric::Swap(Metric* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void Metric::InternalSwap(Metric* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(metric_metadata_, other->metric_metadata_);
+  swap(value_, other->value_);
+  swap(metric_id_, other->metric_id_);
+}
+
+::google::protobuf::Metadata Metric::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void GetMetricRequest::InitAsDefaultInstance() {
+  ::dmi::_GetMetricRequest_default_instance_._instance.get_mutable()->meta_data_ = const_cast< ::dmi::MetricMetaData*>(
+      ::dmi::MetricMetaData::internal_default_instance());
+}
+class GetMetricRequest::HasBitSetters {
+ public:
+  static const ::dmi::MetricMetaData& meta_data(const GetMetricRequest* msg);
+};
+
+const ::dmi::MetricMetaData&
+GetMetricRequest::HasBitSetters::meta_data(const GetMetricRequest* msg) {
+  return *msg->meta_data_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GetMetricRequest::kMetaDataFieldNumber;
+const int GetMetricRequest::kMetricIdFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GetMetricRequest::GetMetricRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.GetMetricRequest)
+}
+GetMetricRequest::GetMetricRequest(const GetMetricRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_meta_data()) {
+    meta_data_ = new ::dmi::MetricMetaData(*from.meta_data_);
+  } else {
+    meta_data_ = nullptr;
+  }
+  metric_id_ = from.metric_id_;
+  // @@protoc_insertion_point(copy_constructor:dmi.GetMetricRequest)
+}
+
+void GetMetricRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_GetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  ::memset(&meta_data_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&metric_id_) -
+      reinterpret_cast<char*>(&meta_data_)) + sizeof(metric_id_));
+}
+
+GetMetricRequest::~GetMetricRequest() {
+  // @@protoc_insertion_point(destructor:dmi.GetMetricRequest)
+  SharedDtor();
+}
+
+void GetMetricRequest::SharedDtor() {
+  if (this != internal_default_instance()) delete meta_data_;
+}
+
+void GetMetricRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const GetMetricRequest& GetMetricRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_GetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void GetMetricRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.GetMetricRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && meta_data_ != nullptr) {
+    delete meta_data_;
+  }
+  meta_data_ = nullptr;
+  metric_id_ = 0;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* GetMetricRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<GetMetricRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.MetricMetaData meta_data = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::MetricMetaData::_InternalParse;
+        object = msg->mutable_meta_data();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.MetricNames metric_id = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_metric_id(static_cast<::dmi::MetricNames>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool GetMetricRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.GetMetricRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.MetricMetaData meta_data = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_meta_data()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.MetricNames metric_id = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_metric_id(static_cast< ::dmi::MetricNames >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.GetMetricRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.GetMetricRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void GetMetricRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.GetMetricRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.MetricMetaData meta_data = 1;
+  if (this->has_meta_data()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::meta_data(this), output);
+  }
+
+  // .dmi.MetricNames metric_id = 2;
+  if (this->metric_id() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->metric_id(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.GetMetricRequest)
+}
+
+::google::protobuf::uint8* GetMetricRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetMetricRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.MetricMetaData meta_data = 1;
+  if (this->has_meta_data()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::meta_data(this), target);
+  }
+
+  // .dmi.MetricNames metric_id = 2;
+  if (this->metric_id() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->metric_id(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetMetricRequest)
+  return target;
+}
+
+size_t GetMetricRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.GetMetricRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.MetricMetaData meta_data = 1;
+  if (this->has_meta_data()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *meta_data_);
+  }
+
+  // .dmi.MetricNames metric_id = 2;
+  if (this->metric_id() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->metric_id());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void GetMetricRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetMetricRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const GetMetricRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<GetMetricRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetMetricRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetMetricRequest)
+    MergeFrom(*source);
+  }
+}
+
+void GetMetricRequest::MergeFrom(const GetMetricRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetMetricRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_meta_data()) {
+    mutable_meta_data()->::dmi::MetricMetaData::MergeFrom(from.meta_data());
+  }
+  if (from.metric_id() != 0) {
+    set_metric_id(from.metric_id());
+  }
+}
+
+void GetMetricRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetMetricRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GetMetricRequest::CopyFrom(const GetMetricRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.GetMetricRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetMetricRequest::IsInitialized() const {
+  return true;
+}
+
+void GetMetricRequest::Swap(GetMetricRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void GetMetricRequest::InternalSwap(GetMetricRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(meta_data_, other->meta_data_);
+  swap(metric_id_, other->metric_id_);
+}
+
+::google::protobuf::Metadata GetMetricRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void GetMetricResponse::InitAsDefaultInstance() {
+  ::dmi::_GetMetricResponse_default_instance_._instance.get_mutable()->metric_ = const_cast< ::dmi::Metric*>(
+      ::dmi::Metric::internal_default_instance());
+}
+class GetMetricResponse::HasBitSetters {
+ public:
+  static const ::dmi::Metric& metric(const GetMetricResponse* msg);
+};
+
+const ::dmi::Metric&
+GetMetricResponse::HasBitSetters::metric(const GetMetricResponse* msg) {
+  return *msg->metric_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GetMetricResponse::kStatusFieldNumber;
+const int GetMetricResponse::kReasonFieldNumber;
+const int GetMetricResponse::kMetricFieldNumber;
+const int GetMetricResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GetMetricResponse::GetMetricResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.GetMetricResponse)
+}
+GetMetricResponse::GetMetricResponse(const GetMetricResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_metric()) {
+    metric_ = new ::dmi::Metric(*from.metric_);
+  } else {
+    metric_ = nullptr;
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.GetMetricResponse)
+}
+
+void GetMetricResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_GetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&metric_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&metric_)) + sizeof(reason_));
+}
+
+GetMetricResponse::~GetMetricResponse() {
+  // @@protoc_insertion_point(destructor:dmi.GetMetricResponse)
+  SharedDtor();
+}
+
+void GetMetricResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete metric_;
+}
+
+void GetMetricResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const GetMetricResponse& GetMetricResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_GetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void GetMetricResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.GetMetricResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && metric_ != nullptr) {
+    delete metric_;
+  }
+  metric_ = nullptr;
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* GetMetricResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<GetMetricResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.GetMetricResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::GetMetricResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.Metric metric = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Metric::_InternalParse;
+        object = msg->mutable_metric();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.GetMetricResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool GetMetricResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.GetMetricResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.GetMetricResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::GetMetricResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.Metric metric = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_metric()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.GetMetricResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.GetMetricResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.GetMetricResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void GetMetricResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.GetMetricResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.GetMetricResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // .dmi.Metric metric = 3;
+  if (this->has_metric()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::metric(this), output);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetMetricResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.GetMetricResponse)
+}
+
+::google::protobuf::uint8* GetMetricResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetMetricResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.GetMetricResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // .dmi.Metric metric = 3;
+  if (this->has_metric()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::metric(this), target);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetMetricResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetMetricResponse)
+  return target;
+}
+
+size_t GetMetricResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.GetMetricResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Metric metric = 3;
+  if (this->has_metric()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *metric_);
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.GetMetricResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void GetMetricResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetMetricResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const GetMetricResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<GetMetricResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetMetricResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetMetricResponse)
+    MergeFrom(*source);
+  }
+}
+
+void GetMetricResponse::MergeFrom(const GetMetricResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetMetricResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_metric()) {
+    mutable_metric()->::dmi::Metric::MergeFrom(from.metric());
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void GetMetricResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetMetricResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GetMetricResponse::CopyFrom(const GetMetricResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.GetMetricResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetMetricResponse::IsInitialized() const {
+  return true;
+}
+
+void GetMetricResponse::Swap(GetMetricResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void GetMetricResponse::InternalSwap(GetMetricResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(metric_, other->metric_);
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata GetMetricResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> PROTOBUF_NOINLINE ::dmi::MetricConfig* Arena::CreateMaybeMessage< ::dmi::MetricConfig >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::MetricConfig >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::MetricsConfig* Arena::CreateMaybeMessage< ::dmi::MetricsConfig >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::MetricsConfig >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ListMetricsResponse* Arena::CreateMaybeMessage< ::dmi::ListMetricsResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ListMetricsResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::MetricsConfigurationRequest* Arena::CreateMaybeMessage< ::dmi::MetricsConfigurationRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::MetricsConfigurationRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::MetricsConfigurationResponse* Arena::CreateMaybeMessage< ::dmi::MetricsConfigurationResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::MetricsConfigurationResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::MetricMetaData* Arena::CreateMaybeMessage< ::dmi::MetricMetaData >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::MetricMetaData >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::Metric* Arena::CreateMaybeMessage< ::dmi::Metric >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::Metric >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::GetMetricRequest* Arena::CreateMaybeMessage< ::dmi::GetMetricRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::GetMetricRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::GetMetricResponse* Arena::CreateMaybeMessage< ::dmi::GetMetricResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::GetMetricResponse >(arena);
+}
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+#include <google/protobuf/port_undef.inc>
diff --git a/cpp/dmi/hw_metrics_mgmt_service.pb.h b/cpp/dmi/hw_metrics_mgmt_service.pb.h
new file mode 100644
index 0000000..5967faa
--- /dev/null
+++ b/cpp/dmi/hw_metrics_mgmt_service.pb.h
@@ -0,0 +1,2481 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/hw_metrics_mgmt_service.proto
+
+#ifndef PROTOBUF_INCLUDED_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto
+#define PROTOBUF_INCLUDED_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto
+
+#include <limits>
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+#if PROTOBUF_VERSION < 3007000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3007000 < PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/port_undef.inc>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/inlined_string_field.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+#include "dmi/commons.pb.h"
+#include "dmi/hw.pb.h"
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+#define PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto
+
+// Internal implementation detail -- do not use these members.
+struct TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto {
+  static const ::google::protobuf::internal::ParseTableField entries[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::AuxillaryParseTableField aux[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::ParseTable schema[9]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
+  static const ::google::protobuf::uint32 offsets[];
+};
+void AddDescriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto();
+namespace dmi {
+class GetMetricRequest;
+class GetMetricRequestDefaultTypeInternal;
+extern GetMetricRequestDefaultTypeInternal _GetMetricRequest_default_instance_;
+class GetMetricResponse;
+class GetMetricResponseDefaultTypeInternal;
+extern GetMetricResponseDefaultTypeInternal _GetMetricResponse_default_instance_;
+class ListMetricsResponse;
+class ListMetricsResponseDefaultTypeInternal;
+extern ListMetricsResponseDefaultTypeInternal _ListMetricsResponse_default_instance_;
+class Metric;
+class MetricDefaultTypeInternal;
+extern MetricDefaultTypeInternal _Metric_default_instance_;
+class MetricConfig;
+class MetricConfigDefaultTypeInternal;
+extern MetricConfigDefaultTypeInternal _MetricConfig_default_instance_;
+class MetricMetaData;
+class MetricMetaDataDefaultTypeInternal;
+extern MetricMetaDataDefaultTypeInternal _MetricMetaData_default_instance_;
+class MetricsConfig;
+class MetricsConfigDefaultTypeInternal;
+extern MetricsConfigDefaultTypeInternal _MetricsConfig_default_instance_;
+class MetricsConfigurationRequest;
+class MetricsConfigurationRequestDefaultTypeInternal;
+extern MetricsConfigurationRequestDefaultTypeInternal _MetricsConfigurationRequest_default_instance_;
+class MetricsConfigurationResponse;
+class MetricsConfigurationResponseDefaultTypeInternal;
+extern MetricsConfigurationResponseDefaultTypeInternal _MetricsConfigurationResponse_default_instance_;
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> ::dmi::GetMetricRequest* Arena::CreateMaybeMessage<::dmi::GetMetricRequest>(Arena*);
+template<> ::dmi::GetMetricResponse* Arena::CreateMaybeMessage<::dmi::GetMetricResponse>(Arena*);
+template<> ::dmi::ListMetricsResponse* Arena::CreateMaybeMessage<::dmi::ListMetricsResponse>(Arena*);
+template<> ::dmi::Metric* Arena::CreateMaybeMessage<::dmi::Metric>(Arena*);
+template<> ::dmi::MetricConfig* Arena::CreateMaybeMessage<::dmi::MetricConfig>(Arena*);
+template<> ::dmi::MetricMetaData* Arena::CreateMaybeMessage<::dmi::MetricMetaData>(Arena*);
+template<> ::dmi::MetricsConfig* Arena::CreateMaybeMessage<::dmi::MetricsConfig>(Arena*);
+template<> ::dmi::MetricsConfigurationRequest* Arena::CreateMaybeMessage<::dmi::MetricsConfigurationRequest>(Arena*);
+template<> ::dmi::MetricsConfigurationResponse* Arena::CreateMaybeMessage<::dmi::MetricsConfigurationResponse>(Arena*);
+}  // namespace protobuf
+}  // namespace google
+namespace dmi {
+
+enum ListMetricsResponse_Reason {
+  ListMetricsResponse_Reason_UNDEFINED_REASON = 0,
+  ListMetricsResponse_Reason_UNKNOWN_DEVICE = 1,
+  ListMetricsResponse_Reason_INTERNAL_ERROR = 2,
+  ListMetricsResponse_Reason_DEVICE_UNREACHABLE = 3,
+  ListMetricsResponse_Reason_ListMetricsResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ListMetricsResponse_Reason_ListMetricsResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ListMetricsResponse_Reason_IsValid(int value);
+const ListMetricsResponse_Reason ListMetricsResponse_Reason_Reason_MIN = ListMetricsResponse_Reason_UNDEFINED_REASON;
+const ListMetricsResponse_Reason ListMetricsResponse_Reason_Reason_MAX = ListMetricsResponse_Reason_DEVICE_UNREACHABLE;
+const int ListMetricsResponse_Reason_Reason_ARRAYSIZE = ListMetricsResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ListMetricsResponse_Reason_descriptor();
+inline const ::std::string& ListMetricsResponse_Reason_Name(ListMetricsResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ListMetricsResponse_Reason_descriptor(), value);
+}
+inline bool ListMetricsResponse_Reason_Parse(
+    const ::std::string& name, ListMetricsResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ListMetricsResponse_Reason>(
+    ListMetricsResponse_Reason_descriptor(), name, value);
+}
+enum MetricsConfigurationResponse_Reason {
+  MetricsConfigurationResponse_Reason_UNDEFINED_REASON = 0,
+  MetricsConfigurationResponse_Reason_UNKNOWN_DEVICE = 1,
+  MetricsConfigurationResponse_Reason_INTERNAL_ERROR = 2,
+  MetricsConfigurationResponse_Reason_POLL_INTERVAL_UNSUPPORTED = 3,
+  MetricsConfigurationResponse_Reason_INVALID_METRIC = 4,
+  MetricsConfigurationResponse_Reason_DEVICE_UNREACHABLE = 5,
+  MetricsConfigurationResponse_Reason_MetricsConfigurationResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  MetricsConfigurationResponse_Reason_MetricsConfigurationResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool MetricsConfigurationResponse_Reason_IsValid(int value);
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse_Reason_Reason_MIN = MetricsConfigurationResponse_Reason_UNDEFINED_REASON;
+const MetricsConfigurationResponse_Reason MetricsConfigurationResponse_Reason_Reason_MAX = MetricsConfigurationResponse_Reason_DEVICE_UNREACHABLE;
+const int MetricsConfigurationResponse_Reason_Reason_ARRAYSIZE = MetricsConfigurationResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* MetricsConfigurationResponse_Reason_descriptor();
+inline const ::std::string& MetricsConfigurationResponse_Reason_Name(MetricsConfigurationResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    MetricsConfigurationResponse_Reason_descriptor(), value);
+}
+inline bool MetricsConfigurationResponse_Reason_Parse(
+    const ::std::string& name, MetricsConfigurationResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<MetricsConfigurationResponse_Reason>(
+    MetricsConfigurationResponse_Reason_descriptor(), name, value);
+}
+enum GetMetricResponse_Reason {
+  GetMetricResponse_Reason_UNDEFINED_REASON = 0,
+  GetMetricResponse_Reason_UNKNOWN_DEVICE = 1,
+  GetMetricResponse_Reason_UNKNOWN_COMPONENT = 2,
+  GetMetricResponse_Reason_INTERNAL_ERROR = 3,
+  GetMetricResponse_Reason_INVALID_METRIC = 4,
+  GetMetricResponse_Reason_DEVICE_UNREACHABLE = 5,
+  GetMetricResponse_Reason_GetMetricResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  GetMetricResponse_Reason_GetMetricResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool GetMetricResponse_Reason_IsValid(int value);
+const GetMetricResponse_Reason GetMetricResponse_Reason_Reason_MIN = GetMetricResponse_Reason_UNDEFINED_REASON;
+const GetMetricResponse_Reason GetMetricResponse_Reason_Reason_MAX = GetMetricResponse_Reason_DEVICE_UNREACHABLE;
+const int GetMetricResponse_Reason_Reason_ARRAYSIZE = GetMetricResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* GetMetricResponse_Reason_descriptor();
+inline const ::std::string& GetMetricResponse_Reason_Name(GetMetricResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    GetMetricResponse_Reason_descriptor(), value);
+}
+inline bool GetMetricResponse_Reason_Parse(
+    const ::std::string& name, GetMetricResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<GetMetricResponse_Reason>(
+    GetMetricResponse_Reason_descriptor(), name, value);
+}
+enum MetricNames {
+  METRIC_NAME_UNDEFINED = 0,
+  METRIC_FAN_SPEED = 1,
+  METRIC_CPU_TEMP = 100,
+  METRIC_CPU_USAGE_PERCENTAGE = 101,
+  METRIC_TRANSCEIVER_TEMP = 200,
+  METRIC_TRANSCEIVER_VOLTAGE = 201,
+  METRIC_TRANSCEIVER_BIAS = 202,
+  METRIC_TRANSCEIVER_RX_POWER = 203,
+  METRIC_TRANSCEIVER_TX_POWER = 204,
+  METRIC_TRANSCEIVER_WAVELENGTH = 205,
+  METRIC_DISK_TEMP = 300,
+  METRIC_DISK_CAPACITY = 301,
+  METRIC_DISK_USAGE = 302,
+  METRIC_DISK_USAGE_PERCENTAGE = 303,
+  METRIC_DISK_READ_WRITE_PERCENTAGE = 304,
+  METRIC_DISK_FAULTY_CELLS_PERCENTAGE = 305,
+  METRIC_RAM_TEMP = 400,
+  METRIC_RAM_CAPACITY = 401,
+  METRIC_RAM_USAGE = 402,
+  METRIC_RAM_USAGE_PERCENTAGE = 403,
+  METRIC_POWER_MAX = 500,
+  METRIC_POWER_USAGE = 501,
+  METRIC_POWER_USAGE_PERCENTAGE = 502,
+  METRIC_INNER_SURROUNDING_TEMP = 600,
+  MetricNames_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  MetricNames_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool MetricNames_IsValid(int value);
+const MetricNames MetricNames_MIN = METRIC_NAME_UNDEFINED;
+const MetricNames MetricNames_MAX = METRIC_INNER_SURROUNDING_TEMP;
+const int MetricNames_ARRAYSIZE = MetricNames_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* MetricNames_descriptor();
+inline const ::std::string& MetricNames_Name(MetricNames value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    MetricNames_descriptor(), value);
+}
+inline bool MetricNames_Parse(
+    const ::std::string& name, MetricNames* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<MetricNames>(
+    MetricNames_descriptor(), name, value);
+}
+// ===================================================================
+
+class MetricConfig final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.MetricConfig) */ {
+ public:
+  MetricConfig();
+  virtual ~MetricConfig();
+
+  MetricConfig(const MetricConfig& from);
+
+  inline MetricConfig& operator=(const MetricConfig& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  MetricConfig(MetricConfig&& from) noexcept
+    : MetricConfig() {
+    *this = ::std::move(from);
+  }
+
+  inline MetricConfig& operator=(MetricConfig&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const MetricConfig& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const MetricConfig* internal_default_instance() {
+    return reinterpret_cast<const MetricConfig*>(
+               &_MetricConfig_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    0;
+
+  void Swap(MetricConfig* other);
+  friend void swap(MetricConfig& a, MetricConfig& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline MetricConfig* New() const final {
+    return CreateMaybeMessage<MetricConfig>(nullptr);
+  }
+
+  MetricConfig* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<MetricConfig>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const MetricConfig& from);
+  void MergeFrom(const MetricConfig& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(MetricConfig* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.MetricNames metric_id = 1;
+  void clear_metric_id();
+  static const int kMetricIdFieldNumber = 1;
+  ::dmi::MetricNames metric_id() const;
+  void set_metric_id(::dmi::MetricNames value);
+
+  // bool is_configured = 2;
+  void clear_is_configured();
+  static const int kIsConfiguredFieldNumber = 2;
+  bool is_configured() const;
+  void set_is_configured(bool value);
+
+  // uint32 poll_interval = 3;
+  void clear_poll_interval();
+  static const int kPollIntervalFieldNumber = 3;
+  ::google::protobuf::uint32 poll_interval() const;
+  void set_poll_interval(::google::protobuf::uint32 value);
+
+  // @@protoc_insertion_point(class_scope:dmi.MetricConfig)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  int metric_id_;
+  bool is_configured_;
+  ::google::protobuf::uint32 poll_interval_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class MetricsConfig final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.MetricsConfig) */ {
+ public:
+  MetricsConfig();
+  virtual ~MetricsConfig();
+
+  MetricsConfig(const MetricsConfig& from);
+
+  inline MetricsConfig& operator=(const MetricsConfig& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  MetricsConfig(MetricsConfig&& from) noexcept
+    : MetricsConfig() {
+    *this = ::std::move(from);
+  }
+
+  inline MetricsConfig& operator=(MetricsConfig&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const MetricsConfig& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const MetricsConfig* internal_default_instance() {
+    return reinterpret_cast<const MetricsConfig*>(
+               &_MetricsConfig_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    1;
+
+  void Swap(MetricsConfig* other);
+  friend void swap(MetricsConfig& a, MetricsConfig& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline MetricsConfig* New() const final {
+    return CreateMaybeMessage<MetricsConfig>(nullptr);
+  }
+
+  MetricsConfig* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<MetricsConfig>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const MetricsConfig& from);
+  void MergeFrom(const MetricsConfig& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(MetricsConfig* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated .dmi.MetricConfig metrics = 1;
+  int metrics_size() const;
+  void clear_metrics();
+  static const int kMetricsFieldNumber = 1;
+  ::dmi::MetricConfig* mutable_metrics(int index);
+  ::google::protobuf::RepeatedPtrField< ::dmi::MetricConfig >*
+      mutable_metrics();
+  const ::dmi::MetricConfig& metrics(int index) const;
+  ::dmi::MetricConfig* add_metrics();
+  const ::google::protobuf::RepeatedPtrField< ::dmi::MetricConfig >&
+      metrics() const;
+
+  // @@protoc_insertion_point(class_scope:dmi.MetricsConfig)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::RepeatedPtrField< ::dmi::MetricConfig > metrics_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ListMetricsResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ListMetricsResponse) */ {
+ public:
+  ListMetricsResponse();
+  virtual ~ListMetricsResponse();
+
+  ListMetricsResponse(const ListMetricsResponse& from);
+
+  inline ListMetricsResponse& operator=(const ListMetricsResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ListMetricsResponse(ListMetricsResponse&& from) noexcept
+    : ListMetricsResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline ListMetricsResponse& operator=(ListMetricsResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ListMetricsResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ListMetricsResponse* internal_default_instance() {
+    return reinterpret_cast<const ListMetricsResponse*>(
+               &_ListMetricsResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    2;
+
+  void Swap(ListMetricsResponse* other);
+  friend void swap(ListMetricsResponse& a, ListMetricsResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ListMetricsResponse* New() const final {
+    return CreateMaybeMessage<ListMetricsResponse>(nullptr);
+  }
+
+  ListMetricsResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ListMetricsResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ListMetricsResponse& from);
+  void MergeFrom(const ListMetricsResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ListMetricsResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef ListMetricsResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    ListMetricsResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    ListMetricsResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    ListMetricsResponse_Reason_INTERNAL_ERROR;
+  static const Reason DEVICE_UNREACHABLE =
+    ListMetricsResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return ListMetricsResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    ListMetricsResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    ListMetricsResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    ListMetricsResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return ListMetricsResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return ListMetricsResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return ListMetricsResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 4;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 4;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.MetricsConfig metrics = 3;
+  bool has_metrics() const;
+  void clear_metrics();
+  static const int kMetricsFieldNumber = 3;
+  const ::dmi::MetricsConfig& metrics() const;
+  ::dmi::MetricsConfig* release_metrics();
+  ::dmi::MetricsConfig* mutable_metrics();
+  void set_allocated_metrics(::dmi::MetricsConfig* metrics);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.ListMetricsResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::ListMetricsResponse_Reason reason() const;
+  void set_reason(::dmi::ListMetricsResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.ListMetricsResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  ::dmi::MetricsConfig* metrics_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class MetricsConfigurationRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.MetricsConfigurationRequest) */ {
+ public:
+  MetricsConfigurationRequest();
+  virtual ~MetricsConfigurationRequest();
+
+  MetricsConfigurationRequest(const MetricsConfigurationRequest& from);
+
+  inline MetricsConfigurationRequest& operator=(const MetricsConfigurationRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  MetricsConfigurationRequest(MetricsConfigurationRequest&& from) noexcept
+    : MetricsConfigurationRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline MetricsConfigurationRequest& operator=(MetricsConfigurationRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const MetricsConfigurationRequest& default_instance();
+
+  enum OperationCase {
+    kChanges = 2,
+    kResetToDefault = 3,
+    OPERATION_NOT_SET = 0,
+  };
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const MetricsConfigurationRequest* internal_default_instance() {
+    return reinterpret_cast<const MetricsConfigurationRequest*>(
+               &_MetricsConfigurationRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    3;
+
+  void Swap(MetricsConfigurationRequest* other);
+  friend void swap(MetricsConfigurationRequest& a, MetricsConfigurationRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline MetricsConfigurationRequest* New() const final {
+    return CreateMaybeMessage<MetricsConfigurationRequest>(nullptr);
+  }
+
+  MetricsConfigurationRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<MetricsConfigurationRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const MetricsConfigurationRequest& from);
+  void MergeFrom(const MetricsConfigurationRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(MetricsConfigurationRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // .dmi.MetricsConfig changes = 2;
+  bool has_changes() const;
+  void clear_changes();
+  static const int kChangesFieldNumber = 2;
+  const ::dmi::MetricsConfig& changes() const;
+  ::dmi::MetricsConfig* release_changes();
+  ::dmi::MetricsConfig* mutable_changes();
+  void set_allocated_changes(::dmi::MetricsConfig* changes);
+
+  // bool reset_to_default = 3;
+  private:
+  bool has_reset_to_default() const;
+  public:
+  void clear_reset_to_default();
+  static const int kResetToDefaultFieldNumber = 3;
+  bool reset_to_default() const;
+  void set_reset_to_default(bool value);
+
+  void clear_operation();
+  OperationCase operation_case() const;
+  // @@protoc_insertion_point(class_scope:dmi.MetricsConfigurationRequest)
+ private:
+  class HasBitSetters;
+  void set_has_changes();
+  void set_has_reset_to_default();
+
+  inline bool has_operation() const;
+  inline void clear_has_operation();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::Uuid* device_uuid_;
+  union OperationUnion {
+    OperationUnion() {}
+    ::dmi::MetricsConfig* changes_;
+    bool reset_to_default_;
+  } operation_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  ::google::protobuf::uint32 _oneof_case_[1];
+
+  friend struct ::TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class MetricsConfigurationResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.MetricsConfigurationResponse) */ {
+ public:
+  MetricsConfigurationResponse();
+  virtual ~MetricsConfigurationResponse();
+
+  MetricsConfigurationResponse(const MetricsConfigurationResponse& from);
+
+  inline MetricsConfigurationResponse& operator=(const MetricsConfigurationResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  MetricsConfigurationResponse(MetricsConfigurationResponse&& from) noexcept
+    : MetricsConfigurationResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline MetricsConfigurationResponse& operator=(MetricsConfigurationResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const MetricsConfigurationResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const MetricsConfigurationResponse* internal_default_instance() {
+    return reinterpret_cast<const MetricsConfigurationResponse*>(
+               &_MetricsConfigurationResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    4;
+
+  void Swap(MetricsConfigurationResponse* other);
+  friend void swap(MetricsConfigurationResponse& a, MetricsConfigurationResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline MetricsConfigurationResponse* New() const final {
+    return CreateMaybeMessage<MetricsConfigurationResponse>(nullptr);
+  }
+
+  MetricsConfigurationResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<MetricsConfigurationResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const MetricsConfigurationResponse& from);
+  void MergeFrom(const MetricsConfigurationResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(MetricsConfigurationResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef MetricsConfigurationResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    MetricsConfigurationResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    MetricsConfigurationResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    MetricsConfigurationResponse_Reason_INTERNAL_ERROR;
+  static const Reason POLL_INTERVAL_UNSUPPORTED =
+    MetricsConfigurationResponse_Reason_POLL_INTERVAL_UNSUPPORTED;
+  static const Reason INVALID_METRIC =
+    MetricsConfigurationResponse_Reason_INVALID_METRIC;
+  static const Reason DEVICE_UNREACHABLE =
+    MetricsConfigurationResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return MetricsConfigurationResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    MetricsConfigurationResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    MetricsConfigurationResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    MetricsConfigurationResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return MetricsConfigurationResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return MetricsConfigurationResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return MetricsConfigurationResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 3;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 3;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.MetricsConfigurationResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::MetricsConfigurationResponse_Reason reason() const;
+  void set_reason(::dmi::MetricsConfigurationResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.MetricsConfigurationResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class MetricMetaData final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.MetricMetaData) */ {
+ public:
+  MetricMetaData();
+  virtual ~MetricMetaData();
+
+  MetricMetaData(const MetricMetaData& from);
+
+  inline MetricMetaData& operator=(const MetricMetaData& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  MetricMetaData(MetricMetaData&& from) noexcept
+    : MetricMetaData() {
+    *this = ::std::move(from);
+  }
+
+  inline MetricMetaData& operator=(MetricMetaData&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const MetricMetaData& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const MetricMetaData* internal_default_instance() {
+    return reinterpret_cast<const MetricMetaData*>(
+               &_MetricMetaData_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    5;
+
+  void Swap(MetricMetaData* other);
+  friend void swap(MetricMetaData& a, MetricMetaData& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline MetricMetaData* New() const final {
+    return CreateMaybeMessage<MetricMetaData>(nullptr);
+  }
+
+  MetricMetaData* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<MetricMetaData>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const MetricMetaData& from);
+  void MergeFrom(const MetricMetaData& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(MetricMetaData* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string component_name = 3;
+  void clear_component_name();
+  static const int kComponentNameFieldNumber = 3;
+  const ::std::string& component_name() const;
+  void set_component_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_component_name(::std::string&& value);
+  #endif
+  void set_component_name(const char* value);
+  void set_component_name(const char* value, size_t size);
+  ::std::string* mutable_component_name();
+  ::std::string* release_component_name();
+  void set_allocated_component_name(::std::string* component_name);
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // .dmi.Uuid component_uuid = 2;
+  bool has_component_uuid() const;
+  void clear_component_uuid();
+  static const int kComponentUuidFieldNumber = 2;
+  const ::dmi::Uuid& component_uuid() const;
+  ::dmi::Uuid* release_component_uuid();
+  ::dmi::Uuid* mutable_component_uuid();
+  void set_allocated_component_uuid(::dmi::Uuid* component_uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.MetricMetaData)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr component_name_;
+  ::dmi::Uuid* device_uuid_;
+  ::dmi::Uuid* component_uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class Metric final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.Metric) */ {
+ public:
+  Metric();
+  virtual ~Metric();
+
+  Metric(const Metric& from);
+
+  inline Metric& operator=(const Metric& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Metric(Metric&& from) noexcept
+    : Metric() {
+    *this = ::std::move(from);
+  }
+
+  inline Metric& operator=(Metric&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const Metric& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Metric* internal_default_instance() {
+    return reinterpret_cast<const Metric*>(
+               &_Metric_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    6;
+
+  void Swap(Metric* other);
+  friend void swap(Metric& a, Metric& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Metric* New() const final {
+    return CreateMaybeMessage<Metric>(nullptr);
+  }
+
+  Metric* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<Metric>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const Metric& from);
+  void MergeFrom(const Metric& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Metric* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.MetricMetaData metric_metadata = 2;
+  bool has_metric_metadata() const;
+  void clear_metric_metadata();
+  static const int kMetricMetadataFieldNumber = 2;
+  const ::dmi::MetricMetaData& metric_metadata() const;
+  ::dmi::MetricMetaData* release_metric_metadata();
+  ::dmi::MetricMetaData* mutable_metric_metadata();
+  void set_allocated_metric_metadata(::dmi::MetricMetaData* metric_metadata);
+
+  // .dmi.ComponentSensorData value = 3;
+  bool has_value() const;
+  void clear_value();
+  static const int kValueFieldNumber = 3;
+  const ::dmi::ComponentSensorData& value() const;
+  ::dmi::ComponentSensorData* release_value();
+  ::dmi::ComponentSensorData* mutable_value();
+  void set_allocated_value(::dmi::ComponentSensorData* value);
+
+  // .dmi.MetricNames metric_id = 1;
+  void clear_metric_id();
+  static const int kMetricIdFieldNumber = 1;
+  ::dmi::MetricNames metric_id() const;
+  void set_metric_id(::dmi::MetricNames value);
+
+  // @@protoc_insertion_point(class_scope:dmi.Metric)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::MetricMetaData* metric_metadata_;
+  ::dmi::ComponentSensorData* value_;
+  int metric_id_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class GetMetricRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.GetMetricRequest) */ {
+ public:
+  GetMetricRequest();
+  virtual ~GetMetricRequest();
+
+  GetMetricRequest(const GetMetricRequest& from);
+
+  inline GetMetricRequest& operator=(const GetMetricRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  GetMetricRequest(GetMetricRequest&& from) noexcept
+    : GetMetricRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline GetMetricRequest& operator=(GetMetricRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const GetMetricRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const GetMetricRequest* internal_default_instance() {
+    return reinterpret_cast<const GetMetricRequest*>(
+               &_GetMetricRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    7;
+
+  void Swap(GetMetricRequest* other);
+  friend void swap(GetMetricRequest& a, GetMetricRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline GetMetricRequest* New() const final {
+    return CreateMaybeMessage<GetMetricRequest>(nullptr);
+  }
+
+  GetMetricRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<GetMetricRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const GetMetricRequest& from);
+  void MergeFrom(const GetMetricRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(GetMetricRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.MetricMetaData meta_data = 1;
+  bool has_meta_data() const;
+  void clear_meta_data();
+  static const int kMetaDataFieldNumber = 1;
+  const ::dmi::MetricMetaData& meta_data() const;
+  ::dmi::MetricMetaData* release_meta_data();
+  ::dmi::MetricMetaData* mutable_meta_data();
+  void set_allocated_meta_data(::dmi::MetricMetaData* meta_data);
+
+  // .dmi.MetricNames metric_id = 2;
+  void clear_metric_id();
+  static const int kMetricIdFieldNumber = 2;
+  ::dmi::MetricNames metric_id() const;
+  void set_metric_id(::dmi::MetricNames value);
+
+  // @@protoc_insertion_point(class_scope:dmi.GetMetricRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::MetricMetaData* meta_data_;
+  int metric_id_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class GetMetricResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.GetMetricResponse) */ {
+ public:
+  GetMetricResponse();
+  virtual ~GetMetricResponse();
+
+  GetMetricResponse(const GetMetricResponse& from);
+
+  inline GetMetricResponse& operator=(const GetMetricResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  GetMetricResponse(GetMetricResponse&& from) noexcept
+    : GetMetricResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline GetMetricResponse& operator=(GetMetricResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const GetMetricResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const GetMetricResponse* internal_default_instance() {
+    return reinterpret_cast<const GetMetricResponse*>(
+               &_GetMetricResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    8;
+
+  void Swap(GetMetricResponse* other);
+  friend void swap(GetMetricResponse& a, GetMetricResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline GetMetricResponse* New() const final {
+    return CreateMaybeMessage<GetMetricResponse>(nullptr);
+  }
+
+  GetMetricResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<GetMetricResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const GetMetricResponse& from);
+  void MergeFrom(const GetMetricResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(GetMetricResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef GetMetricResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    GetMetricResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    GetMetricResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason UNKNOWN_COMPONENT =
+    GetMetricResponse_Reason_UNKNOWN_COMPONENT;
+  static const Reason INTERNAL_ERROR =
+    GetMetricResponse_Reason_INTERNAL_ERROR;
+  static const Reason INVALID_METRIC =
+    GetMetricResponse_Reason_INVALID_METRIC;
+  static const Reason DEVICE_UNREACHABLE =
+    GetMetricResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return GetMetricResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    GetMetricResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    GetMetricResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    GetMetricResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return GetMetricResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return GetMetricResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return GetMetricResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 4;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 4;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Metric metric = 3;
+  bool has_metric() const;
+  void clear_metric();
+  static const int kMetricFieldNumber = 3;
+  const ::dmi::Metric& metric() const;
+  ::dmi::Metric* release_metric();
+  ::dmi::Metric* mutable_metric();
+  void set_allocated_metric(::dmi::Metric* metric);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.GetMetricResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::GetMetricResponse_Reason reason() const;
+  void set_reason(::dmi::GetMetricResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.GetMetricResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  ::dmi::Metric* metric_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// MetricConfig
+
+// .dmi.MetricNames metric_id = 1;
+inline void MetricConfig::clear_metric_id() {
+  metric_id_ = 0;
+}
+inline ::dmi::MetricNames MetricConfig::metric_id() const {
+  // @@protoc_insertion_point(field_get:dmi.MetricConfig.metric_id)
+  return static_cast< ::dmi::MetricNames >(metric_id_);
+}
+inline void MetricConfig::set_metric_id(::dmi::MetricNames value) {
+  
+  metric_id_ = value;
+  // @@protoc_insertion_point(field_set:dmi.MetricConfig.metric_id)
+}
+
+// bool is_configured = 2;
+inline void MetricConfig::clear_is_configured() {
+  is_configured_ = false;
+}
+inline bool MetricConfig::is_configured() const {
+  // @@protoc_insertion_point(field_get:dmi.MetricConfig.is_configured)
+  return is_configured_;
+}
+inline void MetricConfig::set_is_configured(bool value) {
+  
+  is_configured_ = value;
+  // @@protoc_insertion_point(field_set:dmi.MetricConfig.is_configured)
+}
+
+// uint32 poll_interval = 3;
+inline void MetricConfig::clear_poll_interval() {
+  poll_interval_ = 0u;
+}
+inline ::google::protobuf::uint32 MetricConfig::poll_interval() const {
+  // @@protoc_insertion_point(field_get:dmi.MetricConfig.poll_interval)
+  return poll_interval_;
+}
+inline void MetricConfig::set_poll_interval(::google::protobuf::uint32 value) {
+  
+  poll_interval_ = value;
+  // @@protoc_insertion_point(field_set:dmi.MetricConfig.poll_interval)
+}
+
+// -------------------------------------------------------------------
+
+// MetricsConfig
+
+// repeated .dmi.MetricConfig metrics = 1;
+inline int MetricsConfig::metrics_size() const {
+  return metrics_.size();
+}
+inline void MetricsConfig::clear_metrics() {
+  metrics_.Clear();
+}
+inline ::dmi::MetricConfig* MetricsConfig::mutable_metrics(int index) {
+  // @@protoc_insertion_point(field_mutable:dmi.MetricsConfig.metrics)
+  return metrics_.Mutable(index);
+}
+inline ::google::protobuf::RepeatedPtrField< ::dmi::MetricConfig >*
+MetricsConfig::mutable_metrics() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.MetricsConfig.metrics)
+  return &metrics_;
+}
+inline const ::dmi::MetricConfig& MetricsConfig::metrics(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.MetricsConfig.metrics)
+  return metrics_.Get(index);
+}
+inline ::dmi::MetricConfig* MetricsConfig::add_metrics() {
+  // @@protoc_insertion_point(field_add:dmi.MetricsConfig.metrics)
+  return metrics_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::dmi::MetricConfig >&
+MetricsConfig::metrics() const {
+  // @@protoc_insertion_point(field_list:dmi.MetricsConfig.metrics)
+  return metrics_;
+}
+
+// -------------------------------------------------------------------
+
+// ListMetricsResponse
+
+// .dmi.Status status = 1;
+inline void ListMetricsResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status ListMetricsResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.ListMetricsResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void ListMetricsResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ListMetricsResponse.status)
+}
+
+// .dmi.ListMetricsResponse.Reason reason = 2;
+inline void ListMetricsResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::ListMetricsResponse_Reason ListMetricsResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.ListMetricsResponse.reason)
+  return static_cast< ::dmi::ListMetricsResponse_Reason >(reason_);
+}
+inline void ListMetricsResponse::set_reason(::dmi::ListMetricsResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ListMetricsResponse.reason)
+}
+
+// .dmi.MetricsConfig metrics = 3;
+inline bool ListMetricsResponse::has_metrics() const {
+  return this != internal_default_instance() && metrics_ != nullptr;
+}
+inline void ListMetricsResponse::clear_metrics() {
+  if (GetArenaNoVirtual() == nullptr && metrics_ != nullptr) {
+    delete metrics_;
+  }
+  metrics_ = nullptr;
+}
+inline const ::dmi::MetricsConfig& ListMetricsResponse::metrics() const {
+  const ::dmi::MetricsConfig* p = metrics_;
+  // @@protoc_insertion_point(field_get:dmi.ListMetricsResponse.metrics)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::MetricsConfig*>(
+      &::dmi::_MetricsConfig_default_instance_);
+}
+inline ::dmi::MetricsConfig* ListMetricsResponse::release_metrics() {
+  // @@protoc_insertion_point(field_release:dmi.ListMetricsResponse.metrics)
+  
+  ::dmi::MetricsConfig* temp = metrics_;
+  metrics_ = nullptr;
+  return temp;
+}
+inline ::dmi::MetricsConfig* ListMetricsResponse::mutable_metrics() {
+  
+  if (metrics_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::MetricsConfig>(GetArenaNoVirtual());
+    metrics_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ListMetricsResponse.metrics)
+  return metrics_;
+}
+inline void ListMetricsResponse::set_allocated_metrics(::dmi::MetricsConfig* metrics) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete metrics_;
+  }
+  if (metrics) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      metrics = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, metrics, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  metrics_ = metrics;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ListMetricsResponse.metrics)
+}
+
+// string reason_detail = 4;
+inline void ListMetricsResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ListMetricsResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.ListMetricsResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void ListMetricsResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ListMetricsResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void ListMetricsResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ListMetricsResponse.reason_detail)
+}
+#endif
+inline void ListMetricsResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ListMetricsResponse.reason_detail)
+}
+inline void ListMetricsResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ListMetricsResponse.reason_detail)
+}
+inline ::std::string* ListMetricsResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ListMetricsResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ListMetricsResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.ListMetricsResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ListMetricsResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ListMetricsResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// MetricsConfigurationRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool MetricsConfigurationRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& MetricsConfigurationRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.MetricsConfigurationRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* MetricsConfigurationRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.MetricsConfigurationRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* MetricsConfigurationRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.MetricsConfigurationRequest.device_uuid)
+  return device_uuid_;
+}
+inline void MetricsConfigurationRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.MetricsConfigurationRequest.device_uuid)
+}
+
+// .dmi.MetricsConfig changes = 2;
+inline bool MetricsConfigurationRequest::has_changes() const {
+  return operation_case() == kChanges;
+}
+inline void MetricsConfigurationRequest::set_has_changes() {
+  _oneof_case_[0] = kChanges;
+}
+inline void MetricsConfigurationRequest::clear_changes() {
+  if (has_changes()) {
+    delete operation_.changes_;
+    clear_has_operation();
+  }
+}
+inline ::dmi::MetricsConfig* MetricsConfigurationRequest::release_changes() {
+  // @@protoc_insertion_point(field_release:dmi.MetricsConfigurationRequest.changes)
+  if (has_changes()) {
+    clear_has_operation();
+      ::dmi::MetricsConfig* temp = operation_.changes_;
+    operation_.changes_ = nullptr;
+    return temp;
+  } else {
+    return nullptr;
+  }
+}
+inline const ::dmi::MetricsConfig& MetricsConfigurationRequest::changes() const {
+  // @@protoc_insertion_point(field_get:dmi.MetricsConfigurationRequest.changes)
+  return has_changes()
+      ? *operation_.changes_
+      : *reinterpret_cast< ::dmi::MetricsConfig*>(&::dmi::_MetricsConfig_default_instance_);
+}
+inline ::dmi::MetricsConfig* MetricsConfigurationRequest::mutable_changes() {
+  if (!has_changes()) {
+    clear_operation();
+    set_has_changes();
+    operation_.changes_ = CreateMaybeMessage< ::dmi::MetricsConfig >(
+        GetArenaNoVirtual());
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.MetricsConfigurationRequest.changes)
+  return operation_.changes_;
+}
+
+// bool reset_to_default = 3;
+inline bool MetricsConfigurationRequest::has_reset_to_default() const {
+  return operation_case() == kResetToDefault;
+}
+inline void MetricsConfigurationRequest::set_has_reset_to_default() {
+  _oneof_case_[0] = kResetToDefault;
+}
+inline void MetricsConfigurationRequest::clear_reset_to_default() {
+  if (has_reset_to_default()) {
+    operation_.reset_to_default_ = false;
+    clear_has_operation();
+  }
+}
+inline bool MetricsConfigurationRequest::reset_to_default() const {
+  // @@protoc_insertion_point(field_get:dmi.MetricsConfigurationRequest.reset_to_default)
+  if (has_reset_to_default()) {
+    return operation_.reset_to_default_;
+  }
+  return false;
+}
+inline void MetricsConfigurationRequest::set_reset_to_default(bool value) {
+  if (!has_reset_to_default()) {
+    clear_operation();
+    set_has_reset_to_default();
+  }
+  operation_.reset_to_default_ = value;
+  // @@protoc_insertion_point(field_set:dmi.MetricsConfigurationRequest.reset_to_default)
+}
+
+inline bool MetricsConfigurationRequest::has_operation() const {
+  return operation_case() != OPERATION_NOT_SET;
+}
+inline void MetricsConfigurationRequest::clear_has_operation() {
+  _oneof_case_[0] = OPERATION_NOT_SET;
+}
+inline MetricsConfigurationRequest::OperationCase MetricsConfigurationRequest::operation_case() const {
+  return MetricsConfigurationRequest::OperationCase(_oneof_case_[0]);
+}
+// -------------------------------------------------------------------
+
+// MetricsConfigurationResponse
+
+// .dmi.Status status = 1;
+inline void MetricsConfigurationResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status MetricsConfigurationResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.MetricsConfigurationResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void MetricsConfigurationResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.MetricsConfigurationResponse.status)
+}
+
+// .dmi.MetricsConfigurationResponse.Reason reason = 2;
+inline void MetricsConfigurationResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::MetricsConfigurationResponse_Reason MetricsConfigurationResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.MetricsConfigurationResponse.reason)
+  return static_cast< ::dmi::MetricsConfigurationResponse_Reason >(reason_);
+}
+inline void MetricsConfigurationResponse::set_reason(::dmi::MetricsConfigurationResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.MetricsConfigurationResponse.reason)
+}
+
+// string reason_detail = 3;
+inline void MetricsConfigurationResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& MetricsConfigurationResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.MetricsConfigurationResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void MetricsConfigurationResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.MetricsConfigurationResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void MetricsConfigurationResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.MetricsConfigurationResponse.reason_detail)
+}
+#endif
+inline void MetricsConfigurationResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.MetricsConfigurationResponse.reason_detail)
+}
+inline void MetricsConfigurationResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.MetricsConfigurationResponse.reason_detail)
+}
+inline ::std::string* MetricsConfigurationResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.MetricsConfigurationResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* MetricsConfigurationResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.MetricsConfigurationResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void MetricsConfigurationResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.MetricsConfigurationResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// MetricMetaData
+
+// .dmi.Uuid device_uuid = 1;
+inline bool MetricMetaData::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& MetricMetaData::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.MetricMetaData.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* MetricMetaData::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.MetricMetaData.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* MetricMetaData::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.MetricMetaData.device_uuid)
+  return device_uuid_;
+}
+inline void MetricMetaData::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.MetricMetaData.device_uuid)
+}
+
+// .dmi.Uuid component_uuid = 2;
+inline bool MetricMetaData::has_component_uuid() const {
+  return this != internal_default_instance() && component_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& MetricMetaData::component_uuid() const {
+  const ::dmi::Uuid* p = component_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.MetricMetaData.component_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* MetricMetaData::release_component_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.MetricMetaData.component_uuid)
+  
+  ::dmi::Uuid* temp = component_uuid_;
+  component_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* MetricMetaData::mutable_component_uuid() {
+  
+  if (component_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    component_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.MetricMetaData.component_uuid)
+  return component_uuid_;
+}
+inline void MetricMetaData::set_allocated_component_uuid(::dmi::Uuid* component_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(component_uuid_);
+  }
+  if (component_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      component_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, component_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  component_uuid_ = component_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.MetricMetaData.component_uuid)
+}
+
+// string component_name = 3;
+inline void MetricMetaData::clear_component_name() {
+  component_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& MetricMetaData::component_name() const {
+  // @@protoc_insertion_point(field_get:dmi.MetricMetaData.component_name)
+  return component_name_.GetNoArena();
+}
+inline void MetricMetaData::set_component_name(const ::std::string& value) {
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.MetricMetaData.component_name)
+}
+#if LANG_CXX11
+inline void MetricMetaData::set_component_name(::std::string&& value) {
+  
+  component_name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.MetricMetaData.component_name)
+}
+#endif
+inline void MetricMetaData::set_component_name(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.MetricMetaData.component_name)
+}
+inline void MetricMetaData::set_component_name(const char* value, size_t size) {
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.MetricMetaData.component_name)
+}
+inline ::std::string* MetricMetaData::mutable_component_name() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.MetricMetaData.component_name)
+  return component_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* MetricMetaData::release_component_name() {
+  // @@protoc_insertion_point(field_release:dmi.MetricMetaData.component_name)
+  
+  return component_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void MetricMetaData::set_allocated_component_name(::std::string* component_name) {
+  if (component_name != nullptr) {
+    
+  } else {
+    
+  }
+  component_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), component_name);
+  // @@protoc_insertion_point(field_set_allocated:dmi.MetricMetaData.component_name)
+}
+
+// -------------------------------------------------------------------
+
+// Metric
+
+// .dmi.MetricNames metric_id = 1;
+inline void Metric::clear_metric_id() {
+  metric_id_ = 0;
+}
+inline ::dmi::MetricNames Metric::metric_id() const {
+  // @@protoc_insertion_point(field_get:dmi.Metric.metric_id)
+  return static_cast< ::dmi::MetricNames >(metric_id_);
+}
+inline void Metric::set_metric_id(::dmi::MetricNames value) {
+  
+  metric_id_ = value;
+  // @@protoc_insertion_point(field_set:dmi.Metric.metric_id)
+}
+
+// .dmi.MetricMetaData metric_metadata = 2;
+inline bool Metric::has_metric_metadata() const {
+  return this != internal_default_instance() && metric_metadata_ != nullptr;
+}
+inline void Metric::clear_metric_metadata() {
+  if (GetArenaNoVirtual() == nullptr && metric_metadata_ != nullptr) {
+    delete metric_metadata_;
+  }
+  metric_metadata_ = nullptr;
+}
+inline const ::dmi::MetricMetaData& Metric::metric_metadata() const {
+  const ::dmi::MetricMetaData* p = metric_metadata_;
+  // @@protoc_insertion_point(field_get:dmi.Metric.metric_metadata)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::MetricMetaData*>(
+      &::dmi::_MetricMetaData_default_instance_);
+}
+inline ::dmi::MetricMetaData* Metric::release_metric_metadata() {
+  // @@protoc_insertion_point(field_release:dmi.Metric.metric_metadata)
+  
+  ::dmi::MetricMetaData* temp = metric_metadata_;
+  metric_metadata_ = nullptr;
+  return temp;
+}
+inline ::dmi::MetricMetaData* Metric::mutable_metric_metadata() {
+  
+  if (metric_metadata_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::MetricMetaData>(GetArenaNoVirtual());
+    metric_metadata_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Metric.metric_metadata)
+  return metric_metadata_;
+}
+inline void Metric::set_allocated_metric_metadata(::dmi::MetricMetaData* metric_metadata) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete metric_metadata_;
+  }
+  if (metric_metadata) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      metric_metadata = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, metric_metadata, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  metric_metadata_ = metric_metadata;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Metric.metric_metadata)
+}
+
+// .dmi.ComponentSensorData value = 3;
+inline bool Metric::has_value() const {
+  return this != internal_default_instance() && value_ != nullptr;
+}
+inline const ::dmi::ComponentSensorData& Metric::value() const {
+  const ::dmi::ComponentSensorData* p = value_;
+  // @@protoc_insertion_point(field_get:dmi.Metric.value)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ComponentSensorData*>(
+      &::dmi::_ComponentSensorData_default_instance_);
+}
+inline ::dmi::ComponentSensorData* Metric::release_value() {
+  // @@protoc_insertion_point(field_release:dmi.Metric.value)
+  
+  ::dmi::ComponentSensorData* temp = value_;
+  value_ = nullptr;
+  return temp;
+}
+inline ::dmi::ComponentSensorData* Metric::mutable_value() {
+  
+  if (value_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ComponentSensorData>(GetArenaNoVirtual());
+    value_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Metric.value)
+  return value_;
+}
+inline void Metric::set_allocated_value(::dmi::ComponentSensorData* value) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(value_);
+  }
+  if (value) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      value = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, value, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  value_ = value;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Metric.value)
+}
+
+// -------------------------------------------------------------------
+
+// GetMetricRequest
+
+// .dmi.MetricMetaData meta_data = 1;
+inline bool GetMetricRequest::has_meta_data() const {
+  return this != internal_default_instance() && meta_data_ != nullptr;
+}
+inline void GetMetricRequest::clear_meta_data() {
+  if (GetArenaNoVirtual() == nullptr && meta_data_ != nullptr) {
+    delete meta_data_;
+  }
+  meta_data_ = nullptr;
+}
+inline const ::dmi::MetricMetaData& GetMetricRequest::meta_data() const {
+  const ::dmi::MetricMetaData* p = meta_data_;
+  // @@protoc_insertion_point(field_get:dmi.GetMetricRequest.meta_data)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::MetricMetaData*>(
+      &::dmi::_MetricMetaData_default_instance_);
+}
+inline ::dmi::MetricMetaData* GetMetricRequest::release_meta_data() {
+  // @@protoc_insertion_point(field_release:dmi.GetMetricRequest.meta_data)
+  
+  ::dmi::MetricMetaData* temp = meta_data_;
+  meta_data_ = nullptr;
+  return temp;
+}
+inline ::dmi::MetricMetaData* GetMetricRequest::mutable_meta_data() {
+  
+  if (meta_data_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::MetricMetaData>(GetArenaNoVirtual());
+    meta_data_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.GetMetricRequest.meta_data)
+  return meta_data_;
+}
+inline void GetMetricRequest::set_allocated_meta_data(::dmi::MetricMetaData* meta_data) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete meta_data_;
+  }
+  if (meta_data) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      meta_data = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, meta_data, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  meta_data_ = meta_data;
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetMetricRequest.meta_data)
+}
+
+// .dmi.MetricNames metric_id = 2;
+inline void GetMetricRequest::clear_metric_id() {
+  metric_id_ = 0;
+}
+inline ::dmi::MetricNames GetMetricRequest::metric_id() const {
+  // @@protoc_insertion_point(field_get:dmi.GetMetricRequest.metric_id)
+  return static_cast< ::dmi::MetricNames >(metric_id_);
+}
+inline void GetMetricRequest::set_metric_id(::dmi::MetricNames value) {
+  
+  metric_id_ = value;
+  // @@protoc_insertion_point(field_set:dmi.GetMetricRequest.metric_id)
+}
+
+// -------------------------------------------------------------------
+
+// GetMetricResponse
+
+// .dmi.Status status = 1;
+inline void GetMetricResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status GetMetricResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.GetMetricResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void GetMetricResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.GetMetricResponse.status)
+}
+
+// .dmi.GetMetricResponse.Reason reason = 2;
+inline void GetMetricResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::GetMetricResponse_Reason GetMetricResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.GetMetricResponse.reason)
+  return static_cast< ::dmi::GetMetricResponse_Reason >(reason_);
+}
+inline void GetMetricResponse::set_reason(::dmi::GetMetricResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.GetMetricResponse.reason)
+}
+
+// .dmi.Metric metric = 3;
+inline bool GetMetricResponse::has_metric() const {
+  return this != internal_default_instance() && metric_ != nullptr;
+}
+inline void GetMetricResponse::clear_metric() {
+  if (GetArenaNoVirtual() == nullptr && metric_ != nullptr) {
+    delete metric_;
+  }
+  metric_ = nullptr;
+}
+inline const ::dmi::Metric& GetMetricResponse::metric() const {
+  const ::dmi::Metric* p = metric_;
+  // @@protoc_insertion_point(field_get:dmi.GetMetricResponse.metric)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Metric*>(
+      &::dmi::_Metric_default_instance_);
+}
+inline ::dmi::Metric* GetMetricResponse::release_metric() {
+  // @@protoc_insertion_point(field_release:dmi.GetMetricResponse.metric)
+  
+  ::dmi::Metric* temp = metric_;
+  metric_ = nullptr;
+  return temp;
+}
+inline ::dmi::Metric* GetMetricResponse::mutable_metric() {
+  
+  if (metric_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Metric>(GetArenaNoVirtual());
+    metric_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.GetMetricResponse.metric)
+  return metric_;
+}
+inline void GetMetricResponse::set_allocated_metric(::dmi::Metric* metric) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete metric_;
+  }
+  if (metric) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      metric = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, metric, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  metric_ = metric;
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetMetricResponse.metric)
+}
+
+// string reason_detail = 4;
+inline void GetMetricResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& GetMetricResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.GetMetricResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void GetMetricResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.GetMetricResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void GetMetricResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.GetMetricResponse.reason_detail)
+}
+#endif
+inline void GetMetricResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.GetMetricResponse.reason_detail)
+}
+inline void GetMetricResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.GetMetricResponse.reason_detail)
+}
+inline ::std::string* GetMetricResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.GetMetricResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* GetMetricResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.GetMetricResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void GetMetricResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetMetricResponse.reason_detail)
+}
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace dmi
+
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::dmi::ListMetricsResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ListMetricsResponse_Reason>() {
+  return ::dmi::ListMetricsResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::MetricsConfigurationResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::MetricsConfigurationResponse_Reason>() {
+  return ::dmi::MetricsConfigurationResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::GetMetricResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::GetMetricResponse_Reason>() {
+  return ::dmi::GetMetricResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::MetricNames> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::MetricNames>() {
+  return ::dmi::MetricNames_descriptor();
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#include <google/protobuf/port_undef.inc>
+#endif  // PROTOBUF_INCLUDED_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto
diff --git a/cpp/dmi/sw_image.pb.cc b/cpp/dmi/sw_image.pb.cc
new file mode 100644
index 0000000..b96d874
--- /dev/null
+++ b/cpp/dmi/sw_image.pb.cc
@@ -0,0 +1,1657 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/sw_image.proto
+
+#include "dmi/sw_image.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fsw_5fimage_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_ImageVersion_dmi_2fsw_5fimage_2eproto;
+namespace dmi {
+class ImageVersionDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ImageVersion> _instance;
+} _ImageVersion_default_instance_;
+class ImageInformationDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ImageInformation> _instance;
+} _ImageInformation_default_instance_;
+class ImageStatusDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ImageStatus> _instance;
+} _ImageStatus_default_instance_;
+}  // namespace dmi
+static void InitDefaultsImageVersion_dmi_2fsw_5fimage_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ImageVersion_default_instance_;
+    new (ptr) ::dmi::ImageVersion();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ImageVersion::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_ImageVersion_dmi_2fsw_5fimage_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsImageVersion_dmi_2fsw_5fimage_2eproto}, {}};
+
+static void InitDefaultsImageInformation_dmi_2fsw_5fimage_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ImageInformation_default_instance_;
+    new (ptr) ::dmi::ImageInformation();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ImageInformation::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_ImageInformation_dmi_2fsw_5fimage_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsImageInformation_dmi_2fsw_5fimage_2eproto}, {
+      &scc_info_ImageVersion_dmi_2fsw_5fimage_2eproto.base,}};
+
+static void InitDefaultsImageStatus_dmi_2fsw_5fimage_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ImageStatus_default_instance_;
+    new (ptr) ::dmi::ImageStatus();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ImageStatus::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_ImageStatus_dmi_2fsw_5fimage_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsImageStatus_dmi_2fsw_5fimage_2eproto}, {}};
+
+void InitDefaults_dmi_2fsw_5fimage_2eproto() {
+  ::google::protobuf::internal::InitSCC(&scc_info_ImageVersion_dmi_2fsw_5fimage_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ImageInformation_dmi_2fsw_5fimage_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ImageStatus_dmi_2fsw_5fimage_2eproto.base);
+}
+
+::google::protobuf::Metadata file_level_metadata_dmi_2fsw_5fimage_2eproto[3];
+const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors_dmi_2fsw_5fimage_2eproto[2];
+constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_dmi_2fsw_5fimage_2eproto = nullptr;
+
+const ::google::protobuf::uint32 TableStruct_dmi_2fsw_5fimage_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageVersion, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageVersion, image_name_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageVersion, version_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageInformation, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageInformation, image_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageInformation, image_install_script_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageInformation, image_url_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageInformation, sha256sum_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageStatus, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageStatus, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageStatus, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageStatus, state_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageStatus, description_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ImageStatus, reason_detail_),
+};
+static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, -1, sizeof(::dmi::ImageVersion)},
+  { 7, -1, sizeof(::dmi::ImageInformation)},
+  { 16, -1, sizeof(::dmi::ImageStatus)},
+};
+
+static ::google::protobuf::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ImageVersion_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ImageInformation_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ImageStatus_default_instance_),
+};
+
+::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_dmi_2fsw_5fimage_2eproto = {
+  {}, AddDescriptors_dmi_2fsw_5fimage_2eproto, "dmi/sw_image.proto", schemas,
+  file_default_instances, TableStruct_dmi_2fsw_5fimage_2eproto::offsets,
+  file_level_metadata_dmi_2fsw_5fimage_2eproto, 3, file_level_enum_descriptors_dmi_2fsw_5fimage_2eproto, file_level_service_descriptors_dmi_2fsw_5fimage_2eproto,
+};
+
+const char descriptor_table_protodef_dmi_2fsw_5fimage_2eproto[] =
+  "\n\022dmi/sw_image.proto\022\003dmi\032\021dmi/commons.p"
+  "roto\"3\n\014ImageVersion\022\022\n\nimage_name\030\001 \001(\t"
+  "\022\017\n\007version\030\002 \001(\t\"x\n\020ImageInformation\022 \n"
+  "\005image\030\001 \001(\0132\021.dmi.ImageVersion\022\034\n\024image"
+  "_install_script\030\002 \001(\t\022\021\n\timage_url\030\003 \001(\t"
+  "\022\021\n\tsha256sum\030\005 \001(\t\"\342\004\n\013ImageStatus\022\033\n\006s"
+  "tatus\030\001 \001(\0162\013.dmi.Status\022\'\n\006reason\030\002 \001(\016"
+  "2\027.dmi.ImageStatus.Reason\022*\n\005state\030\003 \001(\016"
+  "2\033.dmi.ImageStatus.ImageState\022\023\n\013descrip"
+  "tion\030\004 \001(\t\022\025\n\rreason_detail\030\005 \001(\t\"\320\001\n\nIm"
+  "ageState\022\023\n\017UNDEFINED_STATE\020\000\022\021\n\rCOPYING"
+  "_IMAGE\020\001\022\024\n\020INSTALLING_IMAGE\020\002\022\024\n\020COMMIT"
+  "TING_IMAGE\020\003\022\024\n\020REBOOTING_DEVICE\020\004\022\024\n\020UP"
+  "GRADE_COMPLETE\020\005\022\022\n\016UPGRADE_FAILED\020\006\022\027\n\023"
+  "ACTIVATION_COMPLETE\020\007\022\025\n\021ACTIVATION_FAIL"
+  "ED\020\010\"\341\001\n\006Reason\022\024\n\020UNDEFINED_REASON\020\000\022\024\n"
+  "\020ERROR_IN_REQUEST\020\001\022\022\n\016INTERNAL_ERROR\020\002\022"
+  "\031\n\025DEVICE_IN_WRONG_STATE\020\003\022\021\n\rINVALID_IM"
+  "AGE\020\004\022\030\n\024WRONG_IMAGE_CHECKSUM\020\005\022!\n\035OPERA"
+  "TION_ALREADY_IN_PROGRESS\020\006\022\022\n\016UNKNOWN_DE"
+  "VICE\020\007\022\030\n\024DEVICE_NOT_REACHABLE\020\010B;Z9gith"
+  "ub.com/opencord/device-management-interf"
+  "ace/v3/go/dmib\006proto3"
+  ;
+::google::protobuf::internal::DescriptorTable descriptor_table_dmi_2fsw_5fimage_2eproto = {
+  false, InitDefaults_dmi_2fsw_5fimage_2eproto, 
+  descriptor_table_protodef_dmi_2fsw_5fimage_2eproto,
+  "dmi/sw_image.proto", &assign_descriptors_table_dmi_2fsw_5fimage_2eproto, 901,
+};
+
+void AddDescriptors_dmi_2fsw_5fimage_2eproto() {
+  static constexpr ::google::protobuf::internal::InitFunc deps[1] =
+  {
+    ::AddDescriptors_dmi_2fcommons_2eproto,
+  };
+ ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fsw_5fimage_2eproto, deps, 1);
+}
+
+// Force running AddDescriptors() at dynamic initialization time.
+static bool dynamic_init_dummy_dmi_2fsw_5fimage_2eproto = []() { AddDescriptors_dmi_2fsw_5fimage_2eproto(); return true; }();
+namespace dmi {
+const ::google::protobuf::EnumDescriptor* ImageStatus_ImageState_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fsw_5fimage_2eproto);
+  return file_level_enum_descriptors_dmi_2fsw_5fimage_2eproto[0];
+}
+bool ImageStatus_ImageState_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const ImageStatus_ImageState ImageStatus::UNDEFINED_STATE;
+const ImageStatus_ImageState ImageStatus::COPYING_IMAGE;
+const ImageStatus_ImageState ImageStatus::INSTALLING_IMAGE;
+const ImageStatus_ImageState ImageStatus::COMMITTING_IMAGE;
+const ImageStatus_ImageState ImageStatus::REBOOTING_DEVICE;
+const ImageStatus_ImageState ImageStatus::UPGRADE_COMPLETE;
+const ImageStatus_ImageState ImageStatus::UPGRADE_FAILED;
+const ImageStatus_ImageState ImageStatus::ACTIVATION_COMPLETE;
+const ImageStatus_ImageState ImageStatus::ACTIVATION_FAILED;
+const ImageStatus_ImageState ImageStatus::ImageState_MIN;
+const ImageStatus_ImageState ImageStatus::ImageState_MAX;
+const int ImageStatus::ImageState_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* ImageStatus_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fsw_5fimage_2eproto);
+  return file_level_enum_descriptors_dmi_2fsw_5fimage_2eproto[1];
+}
+bool ImageStatus_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const ImageStatus_Reason ImageStatus::UNDEFINED_REASON;
+const ImageStatus_Reason ImageStatus::ERROR_IN_REQUEST;
+const ImageStatus_Reason ImageStatus::INTERNAL_ERROR;
+const ImageStatus_Reason ImageStatus::DEVICE_IN_WRONG_STATE;
+const ImageStatus_Reason ImageStatus::INVALID_IMAGE;
+const ImageStatus_Reason ImageStatus::WRONG_IMAGE_CHECKSUM;
+const ImageStatus_Reason ImageStatus::OPERATION_ALREADY_IN_PROGRESS;
+const ImageStatus_Reason ImageStatus::UNKNOWN_DEVICE;
+const ImageStatus_Reason ImageStatus::DEVICE_NOT_REACHABLE;
+const ImageStatus_Reason ImageStatus::Reason_MIN;
+const ImageStatus_Reason ImageStatus::Reason_MAX;
+const int ImageStatus::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+// ===================================================================
+
+void ImageVersion::InitAsDefaultInstance() {
+}
+class ImageVersion::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ImageVersion::kImageNameFieldNumber;
+const int ImageVersion::kVersionFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ImageVersion::ImageVersion()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ImageVersion)
+}
+ImageVersion::ImageVersion(const ImageVersion& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  image_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.image_name().size() > 0) {
+    image_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.image_name_);
+  }
+  version_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.version().size() > 0) {
+    version_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.version_);
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.ImageVersion)
+}
+
+void ImageVersion::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ImageVersion_dmi_2fsw_5fimage_2eproto.base);
+  image_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  version_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+ImageVersion::~ImageVersion() {
+  // @@protoc_insertion_point(destructor:dmi.ImageVersion)
+  SharedDtor();
+}
+
+void ImageVersion::SharedDtor() {
+  image_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  version_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void ImageVersion::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ImageVersion& ImageVersion::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ImageVersion_dmi_2fsw_5fimage_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ImageVersion::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ImageVersion)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  image_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ImageVersion::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ImageVersion*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // string image_name = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ImageVersion.image_name");
+        object = msg->mutable_image_name();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string version = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ImageVersion.version");
+        object = msg->mutable_version();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ImageVersion::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ImageVersion)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // string image_name = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_image_name()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->image_name().data(), static_cast<int>(this->image_name().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ImageVersion.image_name"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string version = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_version()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->version().data(), static_cast<int>(this->version().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ImageVersion.version"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ImageVersion)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ImageVersion)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ImageVersion::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ImageVersion)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string image_name = 1;
+  if (this->image_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->image_name().data(), static_cast<int>(this->image_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageVersion.image_name");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      1, this->image_name(), output);
+  }
+
+  // string version = 2;
+  if (this->version().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->version().data(), static_cast<int>(this->version().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageVersion.version");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      2, this->version(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ImageVersion)
+}
+
+::google::protobuf::uint8* ImageVersion::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ImageVersion)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // string image_name = 1;
+  if (this->image_name().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->image_name().data(), static_cast<int>(this->image_name().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageVersion.image_name");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->image_name(), target);
+  }
+
+  // string version = 2;
+  if (this->version().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->version().data(), static_cast<int>(this->version().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageVersion.version");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->version(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ImageVersion)
+  return target;
+}
+
+size_t ImageVersion::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ImageVersion)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string image_name = 1;
+  if (this->image_name().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->image_name());
+  }
+
+  // string version = 2;
+  if (this->version().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->version());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ImageVersion::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ImageVersion)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ImageVersion* source =
+      ::google::protobuf::DynamicCastToGenerated<ImageVersion>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ImageVersion)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ImageVersion)
+    MergeFrom(*source);
+  }
+}
+
+void ImageVersion::MergeFrom(const ImageVersion& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ImageVersion)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.image_name().size() > 0) {
+
+    image_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.image_name_);
+  }
+  if (from.version().size() > 0) {
+
+    version_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.version_);
+  }
+}
+
+void ImageVersion::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ImageVersion)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ImageVersion::CopyFrom(const ImageVersion& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ImageVersion)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ImageVersion::IsInitialized() const {
+  return true;
+}
+
+void ImageVersion::Swap(ImageVersion* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ImageVersion::InternalSwap(ImageVersion* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  image_name_.Swap(&other->image_name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  version_.Swap(&other->version_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+}
+
+::google::protobuf::Metadata ImageVersion::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fimage_2eproto);
+  return ::file_level_metadata_dmi_2fsw_5fimage_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ImageInformation::InitAsDefaultInstance() {
+  ::dmi::_ImageInformation_default_instance_._instance.get_mutable()->image_ = const_cast< ::dmi::ImageVersion*>(
+      ::dmi::ImageVersion::internal_default_instance());
+}
+class ImageInformation::HasBitSetters {
+ public:
+  static const ::dmi::ImageVersion& image(const ImageInformation* msg);
+};
+
+const ::dmi::ImageVersion&
+ImageInformation::HasBitSetters::image(const ImageInformation* msg) {
+  return *msg->image_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ImageInformation::kImageFieldNumber;
+const int ImageInformation::kImageInstallScriptFieldNumber;
+const int ImageInformation::kImageUrlFieldNumber;
+const int ImageInformation::kSha256SumFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ImageInformation::ImageInformation()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ImageInformation)
+}
+ImageInformation::ImageInformation(const ImageInformation& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  image_install_script_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.image_install_script().size() > 0) {
+    image_install_script_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.image_install_script_);
+  }
+  image_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.image_url().size() > 0) {
+    image_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.image_url_);
+  }
+  sha256sum_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.sha256sum().size() > 0) {
+    sha256sum_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.sha256sum_);
+  }
+  if (from.has_image()) {
+    image_ = new ::dmi::ImageVersion(*from.image_);
+  } else {
+    image_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.ImageInformation)
+}
+
+void ImageInformation::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ImageInformation_dmi_2fsw_5fimage_2eproto.base);
+  image_install_script_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  image_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  sha256sum_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  image_ = nullptr;
+}
+
+ImageInformation::~ImageInformation() {
+  // @@protoc_insertion_point(destructor:dmi.ImageInformation)
+  SharedDtor();
+}
+
+void ImageInformation::SharedDtor() {
+  image_install_script_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  image_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  sha256sum_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete image_;
+}
+
+void ImageInformation::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ImageInformation& ImageInformation::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ImageInformation_dmi_2fsw_5fimage_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ImageInformation::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ImageInformation)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  image_install_script_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  image_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  sha256sum_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && image_ != nullptr) {
+    delete image_;
+  }
+  image_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ImageInformation::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ImageInformation*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.ImageVersion image = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::ImageVersion::_InternalParse;
+        object = msg->mutable_image();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string image_install_script = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ImageInformation.image_install_script");
+        object = msg->mutable_image_install_script();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string image_url = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ImageInformation.image_url");
+        object = msg->mutable_image_url();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string sha256sum = 5;
+      case 5: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ImageInformation.sha256sum");
+        object = msg->mutable_sha256sum();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ImageInformation::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ImageInformation)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.ImageVersion image = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_image()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string image_install_script = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_image_install_script()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->image_install_script().data(), static_cast<int>(this->image_install_script().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ImageInformation.image_install_script"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string image_url = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_image_url()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->image_url().data(), static_cast<int>(this->image_url().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ImageInformation.image_url"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string sha256sum = 5;
+      case 5: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (42 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_sha256sum()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->sha256sum().data(), static_cast<int>(this->sha256sum().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ImageInformation.sha256sum"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ImageInformation)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ImageInformation)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ImageInformation::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ImageInformation)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.ImageVersion image = 1;
+  if (this->has_image()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::image(this), output);
+  }
+
+  // string image_install_script = 2;
+  if (this->image_install_script().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->image_install_script().data(), static_cast<int>(this->image_install_script().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageInformation.image_install_script");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      2, this->image_install_script(), output);
+  }
+
+  // string image_url = 3;
+  if (this->image_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->image_url().data(), static_cast<int>(this->image_url().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageInformation.image_url");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->image_url(), output);
+  }
+
+  // string sha256sum = 5;
+  if (this->sha256sum().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->sha256sum().data(), static_cast<int>(this->sha256sum().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageInformation.sha256sum");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      5, this->sha256sum(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ImageInformation)
+}
+
+::google::protobuf::uint8* ImageInformation::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ImageInformation)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.ImageVersion image = 1;
+  if (this->has_image()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::image(this), target);
+  }
+
+  // string image_install_script = 2;
+  if (this->image_install_script().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->image_install_script().data(), static_cast<int>(this->image_install_script().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageInformation.image_install_script");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->image_install_script(), target);
+  }
+
+  // string image_url = 3;
+  if (this->image_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->image_url().data(), static_cast<int>(this->image_url().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageInformation.image_url");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->image_url(), target);
+  }
+
+  // string sha256sum = 5;
+  if (this->sha256sum().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->sha256sum().data(), static_cast<int>(this->sha256sum().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageInformation.sha256sum");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        5, this->sha256sum(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ImageInformation)
+  return target;
+}
+
+size_t ImageInformation::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ImageInformation)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string image_install_script = 2;
+  if (this->image_install_script().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->image_install_script());
+  }
+
+  // string image_url = 3;
+  if (this->image_url().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->image_url());
+  }
+
+  // string sha256sum = 5;
+  if (this->sha256sum().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->sha256sum());
+  }
+
+  // .dmi.ImageVersion image = 1;
+  if (this->has_image()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *image_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ImageInformation::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ImageInformation)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ImageInformation* source =
+      ::google::protobuf::DynamicCastToGenerated<ImageInformation>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ImageInformation)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ImageInformation)
+    MergeFrom(*source);
+  }
+}
+
+void ImageInformation::MergeFrom(const ImageInformation& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ImageInformation)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.image_install_script().size() > 0) {
+
+    image_install_script_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.image_install_script_);
+  }
+  if (from.image_url().size() > 0) {
+
+    image_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.image_url_);
+  }
+  if (from.sha256sum().size() > 0) {
+
+    sha256sum_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.sha256sum_);
+  }
+  if (from.has_image()) {
+    mutable_image()->::dmi::ImageVersion::MergeFrom(from.image());
+  }
+}
+
+void ImageInformation::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ImageInformation)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ImageInformation::CopyFrom(const ImageInformation& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ImageInformation)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ImageInformation::IsInitialized() const {
+  return true;
+}
+
+void ImageInformation::Swap(ImageInformation* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ImageInformation::InternalSwap(ImageInformation* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  image_install_script_.Swap(&other->image_install_script_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  image_url_.Swap(&other->image_url_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  sha256sum_.Swap(&other->sha256sum_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(image_, other->image_);
+}
+
+::google::protobuf::Metadata ImageInformation::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fimage_2eproto);
+  return ::file_level_metadata_dmi_2fsw_5fimage_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ImageStatus::InitAsDefaultInstance() {
+}
+class ImageStatus::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ImageStatus::kStatusFieldNumber;
+const int ImageStatus::kReasonFieldNumber;
+const int ImageStatus::kStateFieldNumber;
+const int ImageStatus::kDescriptionFieldNumber;
+const int ImageStatus::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ImageStatus::ImageStatus()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ImageStatus)
+}
+ImageStatus::ImageStatus(const ImageStatus& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  description_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.description().size() > 0) {
+    description_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.description_);
+  }
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&state_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(state_));
+  // @@protoc_insertion_point(copy_constructor:dmi.ImageStatus)
+}
+
+void ImageStatus::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ImageStatus_dmi_2fsw_5fimage_2eproto.base);
+  description_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&state_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(state_));
+}
+
+ImageStatus::~ImageStatus() {
+  // @@protoc_insertion_point(destructor:dmi.ImageStatus)
+  SharedDtor();
+}
+
+void ImageStatus::SharedDtor() {
+  description_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void ImageStatus::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ImageStatus& ImageStatus::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ImageStatus_dmi_2fsw_5fimage_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ImageStatus::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ImageStatus)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  description_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&state_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(state_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ImageStatus::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ImageStatus*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ImageStatus.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::ImageStatus_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ImageStatus.ImageState state = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_state(static_cast<::dmi::ImageStatus_ImageState>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string description = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ImageStatus.description");
+        object = msg->mutable_description();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string reason_detail = 5;
+      case 5: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ImageStatus.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ImageStatus::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ImageStatus)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ImageStatus.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::ImageStatus_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ImageStatus.ImageState state = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_state(static_cast< ::dmi::ImageStatus_ImageState >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string description = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_description()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->description().data(), static_cast<int>(this->description().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ImageStatus.description"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 5;
+      case 5: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (42 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ImageStatus.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ImageStatus)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ImageStatus)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ImageStatus::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ImageStatus)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.ImageStatus.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // .dmi.ImageStatus.ImageState state = 3;
+  if (this->state() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      3, this->state(), output);
+  }
+
+  // string description = 4;
+  if (this->description().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->description().data(), static_cast<int>(this->description().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageStatus.description");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->description(), output);
+  }
+
+  // string reason_detail = 5;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageStatus.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      5, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ImageStatus)
+}
+
+::google::protobuf::uint8* ImageStatus::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ImageStatus)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.ImageStatus.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // .dmi.ImageStatus.ImageState state = 3;
+  if (this->state() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      3, this->state(), target);
+  }
+
+  // string description = 4;
+  if (this->description().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->description().data(), static_cast<int>(this->description().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageStatus.description");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->description(), target);
+  }
+
+  // string reason_detail = 5;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ImageStatus.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        5, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ImageStatus)
+  return target;
+}
+
+size_t ImageStatus::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ImageStatus)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string description = 4;
+  if (this->description().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->description());
+  }
+
+  // string reason_detail = 5;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.ImageStatus.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  // .dmi.ImageStatus.ImageState state = 3;
+  if (this->state() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->state());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ImageStatus::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ImageStatus)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ImageStatus* source =
+      ::google::protobuf::DynamicCastToGenerated<ImageStatus>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ImageStatus)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ImageStatus)
+    MergeFrom(*source);
+  }
+}
+
+void ImageStatus::MergeFrom(const ImageStatus& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ImageStatus)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.description().size() > 0) {
+
+    description_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.description_);
+  }
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+  if (from.state() != 0) {
+    set_state(from.state());
+  }
+}
+
+void ImageStatus::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ImageStatus)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ImageStatus::CopyFrom(const ImageStatus& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ImageStatus)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ImageStatus::IsInitialized() const {
+  return true;
+}
+
+void ImageStatus::Swap(ImageStatus* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ImageStatus::InternalSwap(ImageStatus* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  description_.Swap(&other->description_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+  swap(state_, other->state_);
+}
+
+::google::protobuf::Metadata ImageStatus::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fimage_2eproto);
+  return ::file_level_metadata_dmi_2fsw_5fimage_2eproto[kIndexInFileMessages];
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> PROTOBUF_NOINLINE ::dmi::ImageVersion* Arena::CreateMaybeMessage< ::dmi::ImageVersion >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ImageVersion >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ImageInformation* Arena::CreateMaybeMessage< ::dmi::ImageInformation >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ImageInformation >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ImageStatus* Arena::CreateMaybeMessage< ::dmi::ImageStatus >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ImageStatus >(arena);
+}
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+#include <google/protobuf/port_undef.inc>
diff --git a/cpp/dmi/sw_image.pb.h b/cpp/dmi/sw_image.pb.h
new file mode 100644
index 0000000..8803132
--- /dev/null
+++ b/cpp/dmi/sw_image.pb.h
@@ -0,0 +1,1175 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/sw_image.proto
+
+#ifndef PROTOBUF_INCLUDED_dmi_2fsw_5fimage_2eproto
+#define PROTOBUF_INCLUDED_dmi_2fsw_5fimage_2eproto
+
+#include <limits>
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+#if PROTOBUF_VERSION < 3007000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3007000 < PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/port_undef.inc>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/inlined_string_field.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+#include "dmi/commons.pb.h"
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+#define PROTOBUF_INTERNAL_EXPORT_dmi_2fsw_5fimage_2eproto
+
+// Internal implementation detail -- do not use these members.
+struct TableStruct_dmi_2fsw_5fimage_2eproto {
+  static const ::google::protobuf::internal::ParseTableField entries[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::AuxillaryParseTableField aux[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::ParseTable schema[3]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
+  static const ::google::protobuf::uint32 offsets[];
+};
+void AddDescriptors_dmi_2fsw_5fimage_2eproto();
+namespace dmi {
+class ImageInformation;
+class ImageInformationDefaultTypeInternal;
+extern ImageInformationDefaultTypeInternal _ImageInformation_default_instance_;
+class ImageStatus;
+class ImageStatusDefaultTypeInternal;
+extern ImageStatusDefaultTypeInternal _ImageStatus_default_instance_;
+class ImageVersion;
+class ImageVersionDefaultTypeInternal;
+extern ImageVersionDefaultTypeInternal _ImageVersion_default_instance_;
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> ::dmi::ImageInformation* Arena::CreateMaybeMessage<::dmi::ImageInformation>(Arena*);
+template<> ::dmi::ImageStatus* Arena::CreateMaybeMessage<::dmi::ImageStatus>(Arena*);
+template<> ::dmi::ImageVersion* Arena::CreateMaybeMessage<::dmi::ImageVersion>(Arena*);
+}  // namespace protobuf
+}  // namespace google
+namespace dmi {
+
+enum ImageStatus_ImageState {
+  ImageStatus_ImageState_UNDEFINED_STATE = 0,
+  ImageStatus_ImageState_COPYING_IMAGE = 1,
+  ImageStatus_ImageState_INSTALLING_IMAGE = 2,
+  ImageStatus_ImageState_COMMITTING_IMAGE = 3,
+  ImageStatus_ImageState_REBOOTING_DEVICE = 4,
+  ImageStatus_ImageState_UPGRADE_COMPLETE = 5,
+  ImageStatus_ImageState_UPGRADE_FAILED = 6,
+  ImageStatus_ImageState_ACTIVATION_COMPLETE = 7,
+  ImageStatus_ImageState_ACTIVATION_FAILED = 8,
+  ImageStatus_ImageState_ImageStatus_ImageState_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ImageStatus_ImageState_ImageStatus_ImageState_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ImageStatus_ImageState_IsValid(int value);
+const ImageStatus_ImageState ImageStatus_ImageState_ImageState_MIN = ImageStatus_ImageState_UNDEFINED_STATE;
+const ImageStatus_ImageState ImageStatus_ImageState_ImageState_MAX = ImageStatus_ImageState_ACTIVATION_FAILED;
+const int ImageStatus_ImageState_ImageState_ARRAYSIZE = ImageStatus_ImageState_ImageState_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ImageStatus_ImageState_descriptor();
+inline const ::std::string& ImageStatus_ImageState_Name(ImageStatus_ImageState value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ImageStatus_ImageState_descriptor(), value);
+}
+inline bool ImageStatus_ImageState_Parse(
+    const ::std::string& name, ImageStatus_ImageState* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ImageStatus_ImageState>(
+    ImageStatus_ImageState_descriptor(), name, value);
+}
+enum ImageStatus_Reason {
+  ImageStatus_Reason_UNDEFINED_REASON = 0,
+  ImageStatus_Reason_ERROR_IN_REQUEST = 1,
+  ImageStatus_Reason_INTERNAL_ERROR = 2,
+  ImageStatus_Reason_DEVICE_IN_WRONG_STATE = 3,
+  ImageStatus_Reason_INVALID_IMAGE = 4,
+  ImageStatus_Reason_WRONG_IMAGE_CHECKSUM = 5,
+  ImageStatus_Reason_OPERATION_ALREADY_IN_PROGRESS = 6,
+  ImageStatus_Reason_UNKNOWN_DEVICE = 7,
+  ImageStatus_Reason_DEVICE_NOT_REACHABLE = 8,
+  ImageStatus_Reason_ImageStatus_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ImageStatus_Reason_ImageStatus_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ImageStatus_Reason_IsValid(int value);
+const ImageStatus_Reason ImageStatus_Reason_Reason_MIN = ImageStatus_Reason_UNDEFINED_REASON;
+const ImageStatus_Reason ImageStatus_Reason_Reason_MAX = ImageStatus_Reason_DEVICE_NOT_REACHABLE;
+const int ImageStatus_Reason_Reason_ARRAYSIZE = ImageStatus_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ImageStatus_Reason_descriptor();
+inline const ::std::string& ImageStatus_Reason_Name(ImageStatus_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ImageStatus_Reason_descriptor(), value);
+}
+inline bool ImageStatus_Reason_Parse(
+    const ::std::string& name, ImageStatus_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ImageStatus_Reason>(
+    ImageStatus_Reason_descriptor(), name, value);
+}
+// ===================================================================
+
+class ImageVersion final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ImageVersion) */ {
+ public:
+  ImageVersion();
+  virtual ~ImageVersion();
+
+  ImageVersion(const ImageVersion& from);
+
+  inline ImageVersion& operator=(const ImageVersion& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ImageVersion(ImageVersion&& from) noexcept
+    : ImageVersion() {
+    *this = ::std::move(from);
+  }
+
+  inline ImageVersion& operator=(ImageVersion&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ImageVersion& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ImageVersion* internal_default_instance() {
+    return reinterpret_cast<const ImageVersion*>(
+               &_ImageVersion_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    0;
+
+  void Swap(ImageVersion* other);
+  friend void swap(ImageVersion& a, ImageVersion& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ImageVersion* New() const final {
+    return CreateMaybeMessage<ImageVersion>(nullptr);
+  }
+
+  ImageVersion* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ImageVersion>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ImageVersion& from);
+  void MergeFrom(const ImageVersion& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ImageVersion* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string image_name = 1;
+  void clear_image_name();
+  static const int kImageNameFieldNumber = 1;
+  const ::std::string& image_name() const;
+  void set_image_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_image_name(::std::string&& value);
+  #endif
+  void set_image_name(const char* value);
+  void set_image_name(const char* value, size_t size);
+  ::std::string* mutable_image_name();
+  ::std::string* release_image_name();
+  void set_allocated_image_name(::std::string* image_name);
+
+  // string version = 2;
+  void clear_version();
+  static const int kVersionFieldNumber = 2;
+  const ::std::string& version() const;
+  void set_version(const ::std::string& value);
+  #if LANG_CXX11
+  void set_version(::std::string&& value);
+  #endif
+  void set_version(const char* value);
+  void set_version(const char* value, size_t size);
+  ::std::string* mutable_version();
+  ::std::string* release_version();
+  void set_allocated_version(::std::string* version);
+
+  // @@protoc_insertion_point(class_scope:dmi.ImageVersion)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr image_name_;
+  ::google::protobuf::internal::ArenaStringPtr version_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fsw_5fimage_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ImageInformation final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ImageInformation) */ {
+ public:
+  ImageInformation();
+  virtual ~ImageInformation();
+
+  ImageInformation(const ImageInformation& from);
+
+  inline ImageInformation& operator=(const ImageInformation& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ImageInformation(ImageInformation&& from) noexcept
+    : ImageInformation() {
+    *this = ::std::move(from);
+  }
+
+  inline ImageInformation& operator=(ImageInformation&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ImageInformation& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ImageInformation* internal_default_instance() {
+    return reinterpret_cast<const ImageInformation*>(
+               &_ImageInformation_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    1;
+
+  void Swap(ImageInformation* other);
+  friend void swap(ImageInformation& a, ImageInformation& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ImageInformation* New() const final {
+    return CreateMaybeMessage<ImageInformation>(nullptr);
+  }
+
+  ImageInformation* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ImageInformation>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ImageInformation& from);
+  void MergeFrom(const ImageInformation& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ImageInformation* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string image_install_script = 2;
+  void clear_image_install_script();
+  static const int kImageInstallScriptFieldNumber = 2;
+  const ::std::string& image_install_script() const;
+  void set_image_install_script(const ::std::string& value);
+  #if LANG_CXX11
+  void set_image_install_script(::std::string&& value);
+  #endif
+  void set_image_install_script(const char* value);
+  void set_image_install_script(const char* value, size_t size);
+  ::std::string* mutable_image_install_script();
+  ::std::string* release_image_install_script();
+  void set_allocated_image_install_script(::std::string* image_install_script);
+
+  // string image_url = 3;
+  void clear_image_url();
+  static const int kImageUrlFieldNumber = 3;
+  const ::std::string& image_url() const;
+  void set_image_url(const ::std::string& value);
+  #if LANG_CXX11
+  void set_image_url(::std::string&& value);
+  #endif
+  void set_image_url(const char* value);
+  void set_image_url(const char* value, size_t size);
+  ::std::string* mutable_image_url();
+  ::std::string* release_image_url();
+  void set_allocated_image_url(::std::string* image_url);
+
+  // string sha256sum = 5;
+  void clear_sha256sum();
+  static const int kSha256SumFieldNumber = 5;
+  const ::std::string& sha256sum() const;
+  void set_sha256sum(const ::std::string& value);
+  #if LANG_CXX11
+  void set_sha256sum(::std::string&& value);
+  #endif
+  void set_sha256sum(const char* value);
+  void set_sha256sum(const char* value, size_t size);
+  ::std::string* mutable_sha256sum();
+  ::std::string* release_sha256sum();
+  void set_allocated_sha256sum(::std::string* sha256sum);
+
+  // .dmi.ImageVersion image = 1;
+  bool has_image() const;
+  void clear_image();
+  static const int kImageFieldNumber = 1;
+  const ::dmi::ImageVersion& image() const;
+  ::dmi::ImageVersion* release_image();
+  ::dmi::ImageVersion* mutable_image();
+  void set_allocated_image(::dmi::ImageVersion* image);
+
+  // @@protoc_insertion_point(class_scope:dmi.ImageInformation)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr image_install_script_;
+  ::google::protobuf::internal::ArenaStringPtr image_url_;
+  ::google::protobuf::internal::ArenaStringPtr sha256sum_;
+  ::dmi::ImageVersion* image_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fsw_5fimage_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ImageStatus final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ImageStatus) */ {
+ public:
+  ImageStatus();
+  virtual ~ImageStatus();
+
+  ImageStatus(const ImageStatus& from);
+
+  inline ImageStatus& operator=(const ImageStatus& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ImageStatus(ImageStatus&& from) noexcept
+    : ImageStatus() {
+    *this = ::std::move(from);
+  }
+
+  inline ImageStatus& operator=(ImageStatus&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ImageStatus& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ImageStatus* internal_default_instance() {
+    return reinterpret_cast<const ImageStatus*>(
+               &_ImageStatus_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    2;
+
+  void Swap(ImageStatus* other);
+  friend void swap(ImageStatus& a, ImageStatus& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ImageStatus* New() const final {
+    return CreateMaybeMessage<ImageStatus>(nullptr);
+  }
+
+  ImageStatus* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ImageStatus>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ImageStatus& from);
+  void MergeFrom(const ImageStatus& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ImageStatus* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef ImageStatus_ImageState ImageState;
+  static const ImageState UNDEFINED_STATE =
+    ImageStatus_ImageState_UNDEFINED_STATE;
+  static const ImageState COPYING_IMAGE =
+    ImageStatus_ImageState_COPYING_IMAGE;
+  static const ImageState INSTALLING_IMAGE =
+    ImageStatus_ImageState_INSTALLING_IMAGE;
+  static const ImageState COMMITTING_IMAGE =
+    ImageStatus_ImageState_COMMITTING_IMAGE;
+  static const ImageState REBOOTING_DEVICE =
+    ImageStatus_ImageState_REBOOTING_DEVICE;
+  static const ImageState UPGRADE_COMPLETE =
+    ImageStatus_ImageState_UPGRADE_COMPLETE;
+  static const ImageState UPGRADE_FAILED =
+    ImageStatus_ImageState_UPGRADE_FAILED;
+  static const ImageState ACTIVATION_COMPLETE =
+    ImageStatus_ImageState_ACTIVATION_COMPLETE;
+  static const ImageState ACTIVATION_FAILED =
+    ImageStatus_ImageState_ACTIVATION_FAILED;
+  static inline bool ImageState_IsValid(int value) {
+    return ImageStatus_ImageState_IsValid(value);
+  }
+  static const ImageState ImageState_MIN =
+    ImageStatus_ImageState_ImageState_MIN;
+  static const ImageState ImageState_MAX =
+    ImageStatus_ImageState_ImageState_MAX;
+  static const int ImageState_ARRAYSIZE =
+    ImageStatus_ImageState_ImageState_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  ImageState_descriptor() {
+    return ImageStatus_ImageState_descriptor();
+  }
+  static inline const ::std::string& ImageState_Name(ImageState value) {
+    return ImageStatus_ImageState_Name(value);
+  }
+  static inline bool ImageState_Parse(const ::std::string& name,
+      ImageState* value) {
+    return ImageStatus_ImageState_Parse(name, value);
+  }
+
+  typedef ImageStatus_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    ImageStatus_Reason_UNDEFINED_REASON;
+  static const Reason ERROR_IN_REQUEST =
+    ImageStatus_Reason_ERROR_IN_REQUEST;
+  static const Reason INTERNAL_ERROR =
+    ImageStatus_Reason_INTERNAL_ERROR;
+  static const Reason DEVICE_IN_WRONG_STATE =
+    ImageStatus_Reason_DEVICE_IN_WRONG_STATE;
+  static const Reason INVALID_IMAGE =
+    ImageStatus_Reason_INVALID_IMAGE;
+  static const Reason WRONG_IMAGE_CHECKSUM =
+    ImageStatus_Reason_WRONG_IMAGE_CHECKSUM;
+  static const Reason OPERATION_ALREADY_IN_PROGRESS =
+    ImageStatus_Reason_OPERATION_ALREADY_IN_PROGRESS;
+  static const Reason UNKNOWN_DEVICE =
+    ImageStatus_Reason_UNKNOWN_DEVICE;
+  static const Reason DEVICE_NOT_REACHABLE =
+    ImageStatus_Reason_DEVICE_NOT_REACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return ImageStatus_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    ImageStatus_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    ImageStatus_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    ImageStatus_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return ImageStatus_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return ImageStatus_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return ImageStatus_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string description = 4;
+  void clear_description();
+  static const int kDescriptionFieldNumber = 4;
+  const ::std::string& description() const;
+  void set_description(const ::std::string& value);
+  #if LANG_CXX11
+  void set_description(::std::string&& value);
+  #endif
+  void set_description(const char* value);
+  void set_description(const char* value, size_t size);
+  ::std::string* mutable_description();
+  ::std::string* release_description();
+  void set_allocated_description(::std::string* description);
+
+  // string reason_detail = 5;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 5;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.ImageStatus.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::ImageStatus_Reason reason() const;
+  void set_reason(::dmi::ImageStatus_Reason value);
+
+  // .dmi.ImageStatus.ImageState state = 3;
+  void clear_state();
+  static const int kStateFieldNumber = 3;
+  ::dmi::ImageStatus_ImageState state() const;
+  void set_state(::dmi::ImageStatus_ImageState value);
+
+  // @@protoc_insertion_point(class_scope:dmi.ImageStatus)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr description_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  int status_;
+  int reason_;
+  int state_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fsw_5fimage_2eproto;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// ImageVersion
+
+// string image_name = 1;
+inline void ImageVersion::clear_image_name() {
+  image_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ImageVersion::image_name() const {
+  // @@protoc_insertion_point(field_get:dmi.ImageVersion.image_name)
+  return image_name_.GetNoArena();
+}
+inline void ImageVersion::set_image_name(const ::std::string& value) {
+  
+  image_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ImageVersion.image_name)
+}
+#if LANG_CXX11
+inline void ImageVersion::set_image_name(::std::string&& value) {
+  
+  image_name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ImageVersion.image_name)
+}
+#endif
+inline void ImageVersion::set_image_name(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  image_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ImageVersion.image_name)
+}
+inline void ImageVersion::set_image_name(const char* value, size_t size) {
+  
+  image_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ImageVersion.image_name)
+}
+inline ::std::string* ImageVersion::mutable_image_name() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ImageVersion.image_name)
+  return image_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ImageVersion::release_image_name() {
+  // @@protoc_insertion_point(field_release:dmi.ImageVersion.image_name)
+  
+  return image_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ImageVersion::set_allocated_image_name(::std::string* image_name) {
+  if (image_name != nullptr) {
+    
+  } else {
+    
+  }
+  image_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), image_name);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ImageVersion.image_name)
+}
+
+// string version = 2;
+inline void ImageVersion::clear_version() {
+  version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ImageVersion::version() const {
+  // @@protoc_insertion_point(field_get:dmi.ImageVersion.version)
+  return version_.GetNoArena();
+}
+inline void ImageVersion::set_version(const ::std::string& value) {
+  
+  version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ImageVersion.version)
+}
+#if LANG_CXX11
+inline void ImageVersion::set_version(::std::string&& value) {
+  
+  version_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ImageVersion.version)
+}
+#endif
+inline void ImageVersion::set_version(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ImageVersion.version)
+}
+inline void ImageVersion::set_version(const char* value, size_t size) {
+  
+  version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ImageVersion.version)
+}
+inline ::std::string* ImageVersion::mutable_version() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ImageVersion.version)
+  return version_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ImageVersion::release_version() {
+  // @@protoc_insertion_point(field_release:dmi.ImageVersion.version)
+  
+  return version_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ImageVersion::set_allocated_version(::std::string* version) {
+  if (version != nullptr) {
+    
+  } else {
+    
+  }
+  version_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), version);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ImageVersion.version)
+}
+
+// -------------------------------------------------------------------
+
+// ImageInformation
+
+// .dmi.ImageVersion image = 1;
+inline bool ImageInformation::has_image() const {
+  return this != internal_default_instance() && image_ != nullptr;
+}
+inline void ImageInformation::clear_image() {
+  if (GetArenaNoVirtual() == nullptr && image_ != nullptr) {
+    delete image_;
+  }
+  image_ = nullptr;
+}
+inline const ::dmi::ImageVersion& ImageInformation::image() const {
+  const ::dmi::ImageVersion* p = image_;
+  // @@protoc_insertion_point(field_get:dmi.ImageInformation.image)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ImageVersion*>(
+      &::dmi::_ImageVersion_default_instance_);
+}
+inline ::dmi::ImageVersion* ImageInformation::release_image() {
+  // @@protoc_insertion_point(field_release:dmi.ImageInformation.image)
+  
+  ::dmi::ImageVersion* temp = image_;
+  image_ = nullptr;
+  return temp;
+}
+inline ::dmi::ImageVersion* ImageInformation::mutable_image() {
+  
+  if (image_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ImageVersion>(GetArenaNoVirtual());
+    image_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ImageInformation.image)
+  return image_;
+}
+inline void ImageInformation::set_allocated_image(::dmi::ImageVersion* image) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete image_;
+  }
+  if (image) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      image = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, image, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  image_ = image;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ImageInformation.image)
+}
+
+// string image_install_script = 2;
+inline void ImageInformation::clear_image_install_script() {
+  image_install_script_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ImageInformation::image_install_script() const {
+  // @@protoc_insertion_point(field_get:dmi.ImageInformation.image_install_script)
+  return image_install_script_.GetNoArena();
+}
+inline void ImageInformation::set_image_install_script(const ::std::string& value) {
+  
+  image_install_script_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ImageInformation.image_install_script)
+}
+#if LANG_CXX11
+inline void ImageInformation::set_image_install_script(::std::string&& value) {
+  
+  image_install_script_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ImageInformation.image_install_script)
+}
+#endif
+inline void ImageInformation::set_image_install_script(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  image_install_script_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ImageInformation.image_install_script)
+}
+inline void ImageInformation::set_image_install_script(const char* value, size_t size) {
+  
+  image_install_script_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ImageInformation.image_install_script)
+}
+inline ::std::string* ImageInformation::mutable_image_install_script() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ImageInformation.image_install_script)
+  return image_install_script_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ImageInformation::release_image_install_script() {
+  // @@protoc_insertion_point(field_release:dmi.ImageInformation.image_install_script)
+  
+  return image_install_script_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ImageInformation::set_allocated_image_install_script(::std::string* image_install_script) {
+  if (image_install_script != nullptr) {
+    
+  } else {
+    
+  }
+  image_install_script_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), image_install_script);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ImageInformation.image_install_script)
+}
+
+// string image_url = 3;
+inline void ImageInformation::clear_image_url() {
+  image_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ImageInformation::image_url() const {
+  // @@protoc_insertion_point(field_get:dmi.ImageInformation.image_url)
+  return image_url_.GetNoArena();
+}
+inline void ImageInformation::set_image_url(const ::std::string& value) {
+  
+  image_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ImageInformation.image_url)
+}
+#if LANG_CXX11
+inline void ImageInformation::set_image_url(::std::string&& value) {
+  
+  image_url_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ImageInformation.image_url)
+}
+#endif
+inline void ImageInformation::set_image_url(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  image_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ImageInformation.image_url)
+}
+inline void ImageInformation::set_image_url(const char* value, size_t size) {
+  
+  image_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ImageInformation.image_url)
+}
+inline ::std::string* ImageInformation::mutable_image_url() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ImageInformation.image_url)
+  return image_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ImageInformation::release_image_url() {
+  // @@protoc_insertion_point(field_release:dmi.ImageInformation.image_url)
+  
+  return image_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ImageInformation::set_allocated_image_url(::std::string* image_url) {
+  if (image_url != nullptr) {
+    
+  } else {
+    
+  }
+  image_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), image_url);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ImageInformation.image_url)
+}
+
+// string sha256sum = 5;
+inline void ImageInformation::clear_sha256sum() {
+  sha256sum_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ImageInformation::sha256sum() const {
+  // @@protoc_insertion_point(field_get:dmi.ImageInformation.sha256sum)
+  return sha256sum_.GetNoArena();
+}
+inline void ImageInformation::set_sha256sum(const ::std::string& value) {
+  
+  sha256sum_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ImageInformation.sha256sum)
+}
+#if LANG_CXX11
+inline void ImageInformation::set_sha256sum(::std::string&& value) {
+  
+  sha256sum_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ImageInformation.sha256sum)
+}
+#endif
+inline void ImageInformation::set_sha256sum(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  sha256sum_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ImageInformation.sha256sum)
+}
+inline void ImageInformation::set_sha256sum(const char* value, size_t size) {
+  
+  sha256sum_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ImageInformation.sha256sum)
+}
+inline ::std::string* ImageInformation::mutable_sha256sum() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ImageInformation.sha256sum)
+  return sha256sum_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ImageInformation::release_sha256sum() {
+  // @@protoc_insertion_point(field_release:dmi.ImageInformation.sha256sum)
+  
+  return sha256sum_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ImageInformation::set_allocated_sha256sum(::std::string* sha256sum) {
+  if (sha256sum != nullptr) {
+    
+  } else {
+    
+  }
+  sha256sum_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), sha256sum);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ImageInformation.sha256sum)
+}
+
+// -------------------------------------------------------------------
+
+// ImageStatus
+
+// .dmi.Status status = 1;
+inline void ImageStatus::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status ImageStatus::status() const {
+  // @@protoc_insertion_point(field_get:dmi.ImageStatus.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void ImageStatus::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ImageStatus.status)
+}
+
+// .dmi.ImageStatus.Reason reason = 2;
+inline void ImageStatus::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::ImageStatus_Reason ImageStatus::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.ImageStatus.reason)
+  return static_cast< ::dmi::ImageStatus_Reason >(reason_);
+}
+inline void ImageStatus::set_reason(::dmi::ImageStatus_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ImageStatus.reason)
+}
+
+// .dmi.ImageStatus.ImageState state = 3;
+inline void ImageStatus::clear_state() {
+  state_ = 0;
+}
+inline ::dmi::ImageStatus_ImageState ImageStatus::state() const {
+  // @@protoc_insertion_point(field_get:dmi.ImageStatus.state)
+  return static_cast< ::dmi::ImageStatus_ImageState >(state_);
+}
+inline void ImageStatus::set_state(::dmi::ImageStatus_ImageState value) {
+  
+  state_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ImageStatus.state)
+}
+
+// string description = 4;
+inline void ImageStatus::clear_description() {
+  description_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ImageStatus::description() const {
+  // @@protoc_insertion_point(field_get:dmi.ImageStatus.description)
+  return description_.GetNoArena();
+}
+inline void ImageStatus::set_description(const ::std::string& value) {
+  
+  description_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ImageStatus.description)
+}
+#if LANG_CXX11
+inline void ImageStatus::set_description(::std::string&& value) {
+  
+  description_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ImageStatus.description)
+}
+#endif
+inline void ImageStatus::set_description(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  description_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ImageStatus.description)
+}
+inline void ImageStatus::set_description(const char* value, size_t size) {
+  
+  description_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ImageStatus.description)
+}
+inline ::std::string* ImageStatus::mutable_description() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ImageStatus.description)
+  return description_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ImageStatus::release_description() {
+  // @@protoc_insertion_point(field_release:dmi.ImageStatus.description)
+  
+  return description_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ImageStatus::set_allocated_description(::std::string* description) {
+  if (description != nullptr) {
+    
+  } else {
+    
+  }
+  description_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), description);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ImageStatus.description)
+}
+
+// string reason_detail = 5;
+inline void ImageStatus::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ImageStatus::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.ImageStatus.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void ImageStatus::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ImageStatus.reason_detail)
+}
+#if LANG_CXX11
+inline void ImageStatus::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ImageStatus.reason_detail)
+}
+#endif
+inline void ImageStatus::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ImageStatus.reason_detail)
+}
+inline void ImageStatus::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ImageStatus.reason_detail)
+}
+inline ::std::string* ImageStatus::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ImageStatus.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ImageStatus::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.ImageStatus.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ImageStatus::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ImageStatus.reason_detail)
+}
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace dmi
+
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::dmi::ImageStatus_ImageState> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ImageStatus_ImageState>() {
+  return ::dmi::ImageStatus_ImageState_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::ImageStatus_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ImageStatus_Reason>() {
+  return ::dmi::ImageStatus_Reason_descriptor();
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#include <google/protobuf/port_undef.inc>
+#endif  // PROTOBUF_INCLUDED_dmi_2fsw_5fimage_2eproto
diff --git a/cpp/dmi/sw_management_service.pb.cc b/cpp/dmi/sw_management_service.pb.cc
new file mode 100644
index 0000000..508dd63
--- /dev/null
+++ b/cpp/dmi/sw_management_service.pb.cc
@@ -0,0 +1,3207 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/sw_management_service.proto
+
+#include "dmi/sw_management_service.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Uuid_dmi_2fhw_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fsw_5fimage_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_ImageVersion_dmi_2fsw_5fimage_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fsw_5fimage_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_ImageInformation_dmi_2fsw_5fimage_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_dmi_2fsw_5fmanagement_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_SoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto;
+namespace dmi {
+class SoftwareVersionInformationDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<SoftwareVersionInformation> _instance;
+} _SoftwareVersionInformation_default_instance_;
+class GetSoftwareVersionInformationResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<GetSoftwareVersionInformationResponse> _instance;
+} _GetSoftwareVersionInformationResponse_default_instance_;
+class DownloadImageRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<DownloadImageRequest> _instance;
+} _DownloadImageRequest_default_instance_;
+class ConfigRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ConfigRequest> _instance;
+} _ConfigRequest_default_instance_;
+class ConfigResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<ConfigResponse> _instance;
+} _ConfigResponse_default_instance_;
+class StartupConfigInfoRequestDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<StartupConfigInfoRequest> _instance;
+} _StartupConfigInfoRequest_default_instance_;
+class StartupConfigInfoResponseDefaultTypeInternal {
+ public:
+  ::google::protobuf::internal::ExplicitlyConstructed<StartupConfigInfoResponse> _instance;
+} _StartupConfigInfoResponse_default_instance_;
+}  // namespace dmi
+static void InitDefaultsSoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_SoftwareVersionInformation_default_instance_;
+    new (ptr) ::dmi::SoftwareVersionInformation();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::SoftwareVersionInformation::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_SoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsSoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_ImageVersion_dmi_2fsw_5fimage_2eproto.base,}};
+
+static void InitDefaultsGetSoftwareVersionInformationResponse_dmi_2fsw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_GetSoftwareVersionInformationResponse_default_instance_;
+    new (ptr) ::dmi::GetSoftwareVersionInformationResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::GetSoftwareVersionInformationResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_GetSoftwareVersionInformationResponse_dmi_2fsw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsGetSoftwareVersionInformationResponse_dmi_2fsw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_SoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto.base,}};
+
+static void InitDefaultsDownloadImageRequest_dmi_2fsw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_DownloadImageRequest_default_instance_;
+    new (ptr) ::dmi::DownloadImageRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::DownloadImageRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<2> scc_info_DownloadImageRequest_dmi_2fsw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsDownloadImageRequest_dmi_2fsw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,
+      &scc_info_ImageInformation_dmi_2fsw_5fimage_2eproto.base,}};
+
+static void InitDefaultsConfigRequest_dmi_2fsw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ConfigRequest_default_instance_;
+    new (ptr) ::dmi::ConfigRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ConfigRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_ConfigRequest_dmi_2fsw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsConfigRequest_dmi_2fsw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsConfigResponse_dmi_2fsw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_ConfigResponse_default_instance_;
+    new (ptr) ::dmi::ConfigResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::ConfigResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_ConfigResponse_dmi_2fsw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsConfigResponse_dmi_2fsw_5fmanagement_5fservice_2eproto}, {}};
+
+static void InitDefaultsStartupConfigInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_StartupConfigInfoRequest_default_instance_;
+    new (ptr) ::dmi::StartupConfigInfoRequest();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::StartupConfigInfoRequest::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<1> scc_info_StartupConfigInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsStartupConfigInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto}, {
+      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};
+
+static void InitDefaultsStartupConfigInfoResponse_dmi_2fsw_5fmanagement_5fservice_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::dmi::_StartupConfigInfoResponse_default_instance_;
+    new (ptr) ::dmi::StartupConfigInfoResponse();
+    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
+  }
+  ::dmi::StartupConfigInfoResponse::InitAsDefaultInstance();
+}
+
+::google::protobuf::internal::SCCInfo<0> scc_info_StartupConfigInfoResponse_dmi_2fsw_5fmanagement_5fservice_2eproto =
+    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsStartupConfigInfoResponse_dmi_2fsw_5fmanagement_5fservice_2eproto}, {}};
+
+void InitDefaults_dmi_2fsw_5fmanagement_5fservice_2eproto() {
+  ::google::protobuf::internal::InitSCC(&scc_info_SoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_GetSoftwareVersionInformationResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_DownloadImageRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ConfigRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_ConfigResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_StartupConfigInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  ::google::protobuf::internal::InitSCC(&scc_info_StartupConfigInfoResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+}
+
+::google::protobuf::Metadata file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[7];
+const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto[3];
+constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto = nullptr;
+
+const ::google::protobuf::uint32 TableStruct_dmi_2fsw_5fmanagement_5fservice_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::SoftwareVersionInformation, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::SoftwareVersionInformation, active_versions_),
+  PROTOBUF_FIELD_OFFSET(::dmi::SoftwareVersionInformation, standby_versions_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetSoftwareVersionInformationResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::GetSoftwareVersionInformationResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetSoftwareVersionInformationResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetSoftwareVersionInformationResponse, info_),
+  PROTOBUF_FIELD_OFFSET(::dmi::GetSoftwareVersionInformationResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::DownloadImageRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::DownloadImageRequest, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::DownloadImageRequest, image_info_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ConfigRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ConfigRequest, device_uuid_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ConfigRequest, config_url_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::ConfigResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::ConfigResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ConfigResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::ConfigResponse, reason_detail_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoRequest, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoRequest, device_uuid_),
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoResponse, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoResponse, status_),
+  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoResponse, reason_),
+  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoResponse, config_url_),
+  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoResponse, version_),
+  PROTOBUF_FIELD_OFFSET(::dmi::StartupConfigInfoResponse, reason_detail_),
+};
+static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, -1, sizeof(::dmi::SoftwareVersionInformation)},
+  { 7, -1, sizeof(::dmi::GetSoftwareVersionInformationResponse)},
+  { 16, -1, sizeof(::dmi::DownloadImageRequest)},
+  { 23, -1, sizeof(::dmi::ConfigRequest)},
+  { 30, -1, sizeof(::dmi::ConfigResponse)},
+  { 38, -1, sizeof(::dmi::StartupConfigInfoRequest)},
+  { 44, -1, sizeof(::dmi::StartupConfigInfoResponse)},
+};
+
+static ::google::protobuf::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_SoftwareVersionInformation_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetSoftwareVersionInformationResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_DownloadImageRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ConfigRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ConfigResponse_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_StartupConfigInfoRequest_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_StartupConfigInfoResponse_default_instance_),
+};
+
+::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto = {
+  {}, AddDescriptors_dmi_2fsw_5fmanagement_5fservice_2eproto, "dmi/sw_management_service.proto", schemas,
+  file_default_instances, TableStruct_dmi_2fsw_5fmanagement_5fservice_2eproto::offsets,
+  file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto, 7, file_level_enum_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto, file_level_service_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto,
+};
+
+const char descriptor_table_protodef_dmi_2fsw_5fmanagement_5fservice_2eproto[] =
+  "\n\037dmi/sw_management_service.proto\022\003dmi\032\021"
+  "dmi/commons.proto\032\014dmi/hw.proto\032\022dmi/sw_"
+  "image.proto\"u\n\032SoftwareVersionInformatio"
+  "n\022*\n\017active_versions\030\001 \003(\0132\021.dmi.ImageVe"
+  "rsion\022+\n\020standby_versions\030\002 \003(\0132\021.dmi.Im"
+  "ageVersion\"\255\002\n%GetSoftwareVersionInforma"
+  "tionResponse\022\033\n\006status\030\001 \001(\0162\013.dmi.Statu"
+  "s\022A\n\006reason\030\002 \001(\01621.dmi.GetSoftwareVersi"
+  "onInformationResponse.Reason\022-\n\004info\030\003 \001"
+  "(\0132\037.dmi.SoftwareVersionInformation\022\025\n\rr"
+  "eason_detail\030\004 \001(\t\"^\n\006Reason\022\024\n\020UNDEFINE"
+  "D_REASON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERN"
+  "AL_ERROR\020\002\022\026\n\022DEVICE_UNREACHABLE\020\003\"a\n\024Do"
+  "wnloadImageRequest\022\036\n\013device_uuid\030\001 \001(\0132"
+  "\t.dmi.Uuid\022)\n\nimage_info\030\002 \001(\0132\025.dmi.Ima"
+  "geInformation\"C\n\rConfigRequest\022\036\n\013device"
+  "_uuid\030\001 \001(\0132\t.dmi.Uuid\022\022\n\nconfig_url\030\002 \001"
+  "(\t\"\243\002\n\016ConfigResponse\022\033\n\006status\030\001 \001(\0162\013."
+  "dmi.Status\022*\n\006reason\030\002 \001(\0162\032.dmi.ConfigR"
+  "esponse.Reason\022\025\n\rreason_detail\030\003 \001(\t\"\260\001"
+  "\n\006Reason\022\024\n\020UNDEFINED_REASON\020\000\022\022\n\016UNKNOW"
+  "N_DEVICE\020\001\022\022\n\016INTERNAL_ERROR\020\002\022\031\n\025ERROR_"
+  "FETCHING_CONFIG\020\003\022\022\n\016INVALID_CONFIG\020\004\022!\n"
+  "\035OPERATION_ALREADY_IN_PROGRESS\020\005\022\026\n\022DEVI"
+  "CE_UNREACHABLE\020\006\":\n\030StartupConfigInfoReq"
+  "uest\022\036\n\013device_uuid\030\001 \001(\0132\t.dmi.Uuid\"\213\002\n"
+  "\031StartupConfigInfoResponse\022\033\n\006status\030\001 \001"
+  "(\0162\013.dmi.Status\0225\n\006reason\030\002 \001(\0162%.dmi.St"
+  "artupConfigInfoResponse.Reason\022\022\n\nconfig"
+  "_url\030\003 \001(\t\022\017\n\007version\030\004 \001(\t\022\025\n\rreason_de"
+  "tail\030\005 \001(\t\"^\n\006Reason\022\024\n\020UNDEFINED_REASON"
+  "\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERNAL_ERROR"
+  "\020\002\022\026\n\022DEVICE_UNREACHABLE\020\0032\316\003\n\037NativeSof"
+  "twareManagementService\022Q\n\022GetSoftwareVer"
+  "sion\022\017.dmi.HardwareID\032*.dmi.GetSoftwareV"
+  "ersionInformationResponse\022>\n\rDownloadIma"
+  "ge\022\031.dmi.DownloadImageRequest\032\020.dmi.Imag"
+  "eStatus0\001\0224\n\rActivateImage\022\017.dmi.Hardwar"
+  "eID\032\020.dmi.ImageStatus0\001\022;\n\024RevertToStand"
+  "byImage\022\017.dmi.HardwareID\032\020.dmi.ImageStat"
+  "us0\001\022G\n\032UpdateStartupConfiguration\022\022.dmi"
+  ".ConfigRequest\032\023.dmi.ConfigResponse0\001\022\\\n"
+  "\033GetStartupConfigurationInfo\022\035.dmi.Start"
+  "upConfigInfoRequest\032\036.dmi.StartupConfigI"
+  "nfoResponseB;Z9github.com/opencord/devic"
+  "e-management-interface/v3/go/dmib\006proto3"
+  ;
+::google::protobuf::internal::DescriptorTable descriptor_table_dmi_2fsw_5fmanagement_5fservice_2eproto = {
+  false, InitDefaults_dmi_2fsw_5fmanagement_5fservice_2eproto, 
+  descriptor_table_protodef_dmi_2fsw_5fmanagement_5fservice_2eproto,
+  "dmi/sw_management_service.proto", &assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto, 1840,
+};
+
+void AddDescriptors_dmi_2fsw_5fmanagement_5fservice_2eproto() {
+  static constexpr ::google::protobuf::internal::InitFunc deps[3] =
+  {
+    ::AddDescriptors_dmi_2fcommons_2eproto,
+    ::AddDescriptors_dmi_2fhw_2eproto,
+    ::AddDescriptors_dmi_2fsw_5fimage_2eproto,
+  };
+ ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fsw_5fmanagement_5fservice_2eproto, deps, 3);
+}
+
+// Force running AddDescriptors() at dynamic initialization time.
+static bool dynamic_init_dummy_dmi_2fsw_5fmanagement_5fservice_2eproto = []() { AddDescriptors_dmi_2fsw_5fmanagement_5fservice_2eproto(); return true; }();
+namespace dmi {
+const ::google::protobuf::EnumDescriptor* GetSoftwareVersionInformationResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto[0];
+}
+bool GetSoftwareVersionInformationResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::UNDEFINED_REASON;
+const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::UNKNOWN_DEVICE;
+const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::INTERNAL_ERROR;
+const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::DEVICE_UNREACHABLE;
+const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::Reason_MIN;
+const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::Reason_MAX;
+const int GetSoftwareVersionInformationResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* ConfigResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto[1];
+}
+bool ConfigResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const ConfigResponse_Reason ConfigResponse::UNDEFINED_REASON;
+const ConfigResponse_Reason ConfigResponse::UNKNOWN_DEVICE;
+const ConfigResponse_Reason ConfigResponse::INTERNAL_ERROR;
+const ConfigResponse_Reason ConfigResponse::ERROR_FETCHING_CONFIG;
+const ConfigResponse_Reason ConfigResponse::INVALID_CONFIG;
+const ConfigResponse_Reason ConfigResponse::OPERATION_ALREADY_IN_PROGRESS;
+const ConfigResponse_Reason ConfigResponse::DEVICE_UNREACHABLE;
+const ConfigResponse_Reason ConfigResponse::Reason_MIN;
+const ConfigResponse_Reason ConfigResponse::Reason_MAX;
+const int ConfigResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+const ::google::protobuf::EnumDescriptor* StartupConfigInfoResponse_Reason_descriptor() {
+  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
+  return file_level_enum_descriptors_dmi_2fsw_5fmanagement_5fservice_2eproto[2];
+}
+bool StartupConfigInfoResponse_Reason_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const StartupConfigInfoResponse_Reason StartupConfigInfoResponse::UNDEFINED_REASON;
+const StartupConfigInfoResponse_Reason StartupConfigInfoResponse::UNKNOWN_DEVICE;
+const StartupConfigInfoResponse_Reason StartupConfigInfoResponse::INTERNAL_ERROR;
+const StartupConfigInfoResponse_Reason StartupConfigInfoResponse::DEVICE_UNREACHABLE;
+const StartupConfigInfoResponse_Reason StartupConfigInfoResponse::Reason_MIN;
+const StartupConfigInfoResponse_Reason StartupConfigInfoResponse::Reason_MAX;
+const int StartupConfigInfoResponse::Reason_ARRAYSIZE;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+// ===================================================================
+
+void SoftwareVersionInformation::InitAsDefaultInstance() {
+}
+class SoftwareVersionInformation::HasBitSetters {
+ public:
+};
+
+void SoftwareVersionInformation::clear_active_versions() {
+  active_versions_.Clear();
+}
+void SoftwareVersionInformation::clear_standby_versions() {
+  standby_versions_.Clear();
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int SoftwareVersionInformation::kActiveVersionsFieldNumber;
+const int SoftwareVersionInformation::kStandbyVersionsFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+SoftwareVersionInformation::SoftwareVersionInformation()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.SoftwareVersionInformation)
+}
+SoftwareVersionInformation::SoftwareVersionInformation(const SoftwareVersionInformation& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr),
+      active_versions_(from.active_versions_),
+      standby_versions_(from.standby_versions_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  // @@protoc_insertion_point(copy_constructor:dmi.SoftwareVersionInformation)
+}
+
+void SoftwareVersionInformation::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_SoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+}
+
+SoftwareVersionInformation::~SoftwareVersionInformation() {
+  // @@protoc_insertion_point(destructor:dmi.SoftwareVersionInformation)
+  SharedDtor();
+}
+
+void SoftwareVersionInformation::SharedDtor() {
+}
+
+void SoftwareVersionInformation::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const SoftwareVersionInformation& SoftwareVersionInformation::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_SoftwareVersionInformation_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void SoftwareVersionInformation::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.SoftwareVersionInformation)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  active_versions_.Clear();
+  standby_versions_.Clear();
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* SoftwareVersionInformation::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<SoftwareVersionInformation*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // repeated .dmi.ImageVersion active_versions = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        do {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          parser_till_end = ::dmi::ImageVersion::_InternalParse;
+          object = msg->add_active_versions();
+          if (size > end - ptr) goto len_delim_till_end;
+          ptr += size;
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+              {parser_till_end, object}, ptr - size, ptr));
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 10 && (ptr += 1));
+        break;
+      }
+      // repeated .dmi.ImageVersion standby_versions = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        do {
+          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+          parser_till_end = ::dmi::ImageVersion::_InternalParse;
+          object = msg->add_standby_versions();
+          if (size > end - ptr) goto len_delim_till_end;
+          ptr += size;
+          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+              {parser_till_end, object}, ptr - size, ptr));
+          if (ptr >= end) break;
+        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 18 && (ptr += 1));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool SoftwareVersionInformation::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.SoftwareVersionInformation)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .dmi.ImageVersion active_versions = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+                input, add_active_versions()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // repeated .dmi.ImageVersion standby_versions = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+                input, add_standby_versions()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.SoftwareVersionInformation)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.SoftwareVersionInformation)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void SoftwareVersionInformation::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.SoftwareVersionInformation)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // repeated .dmi.ImageVersion active_versions = 1;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->active_versions_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1,
+      this->active_versions(static_cast<int>(i)),
+      output);
+  }
+
+  // repeated .dmi.ImageVersion standby_versions = 2;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->standby_versions_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2,
+      this->standby_versions(static_cast<int>(i)),
+      output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.SoftwareVersionInformation)
+}
+
+::google::protobuf::uint8* SoftwareVersionInformation::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.SoftwareVersionInformation)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // repeated .dmi.ImageVersion active_versions = 1;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->active_versions_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, this->active_versions(static_cast<int>(i)), target);
+  }
+
+  // repeated .dmi.ImageVersion standby_versions = 2;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->standby_versions_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, this->standby_versions(static_cast<int>(i)), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.SoftwareVersionInformation)
+  return target;
+}
+
+size_t SoftwareVersionInformation::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.SoftwareVersionInformation)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // repeated .dmi.ImageVersion active_versions = 1;
+  {
+    unsigned int count = static_cast<unsigned int>(this->active_versions_size());
+    total_size += 1UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->active_versions(static_cast<int>(i)));
+    }
+  }
+
+  // repeated .dmi.ImageVersion standby_versions = 2;
+  {
+    unsigned int count = static_cast<unsigned int>(this->standby_versions_size());
+    total_size += 1UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSize(
+          this->standby_versions(static_cast<int>(i)));
+    }
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void SoftwareVersionInformation::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.SoftwareVersionInformation)
+  GOOGLE_DCHECK_NE(&from, this);
+  const SoftwareVersionInformation* source =
+      ::google::protobuf::DynamicCastToGenerated<SoftwareVersionInformation>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.SoftwareVersionInformation)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.SoftwareVersionInformation)
+    MergeFrom(*source);
+  }
+}
+
+void SoftwareVersionInformation::MergeFrom(const SoftwareVersionInformation& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.SoftwareVersionInformation)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  active_versions_.MergeFrom(from.active_versions_);
+  standby_versions_.MergeFrom(from.standby_versions_);
+}
+
+void SoftwareVersionInformation::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.SoftwareVersionInformation)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SoftwareVersionInformation::CopyFrom(const SoftwareVersionInformation& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.SoftwareVersionInformation)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool SoftwareVersionInformation::IsInitialized() const {
+  return true;
+}
+
+void SoftwareVersionInformation::Swap(SoftwareVersionInformation* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void SoftwareVersionInformation::InternalSwap(SoftwareVersionInformation* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  CastToBase(&active_versions_)->InternalSwap(CastToBase(&other->active_versions_));
+  CastToBase(&standby_versions_)->InternalSwap(CastToBase(&other->standby_versions_));
+}
+
+::google::protobuf::Metadata SoftwareVersionInformation::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void GetSoftwareVersionInformationResponse::InitAsDefaultInstance() {
+  ::dmi::_GetSoftwareVersionInformationResponse_default_instance_._instance.get_mutable()->info_ = const_cast< ::dmi::SoftwareVersionInformation*>(
+      ::dmi::SoftwareVersionInformation::internal_default_instance());
+}
+class GetSoftwareVersionInformationResponse::HasBitSetters {
+ public:
+  static const ::dmi::SoftwareVersionInformation& info(const GetSoftwareVersionInformationResponse* msg);
+};
+
+const ::dmi::SoftwareVersionInformation&
+GetSoftwareVersionInformationResponse::HasBitSetters::info(const GetSoftwareVersionInformationResponse* msg) {
+  return *msg->info_;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int GetSoftwareVersionInformationResponse::kStatusFieldNumber;
+const int GetSoftwareVersionInformationResponse::kReasonFieldNumber;
+const int GetSoftwareVersionInformationResponse::kInfoFieldNumber;
+const int GetSoftwareVersionInformationResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+GetSoftwareVersionInformationResponse::GetSoftwareVersionInformationResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.GetSoftwareVersionInformationResponse)
+}
+GetSoftwareVersionInformationResponse::GetSoftwareVersionInformationResponse(const GetSoftwareVersionInformationResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_info()) {
+    info_ = new ::dmi::SoftwareVersionInformation(*from.info_);
+  } else {
+    info_ = nullptr;
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.GetSoftwareVersionInformationResponse)
+}
+
+void GetSoftwareVersionInformationResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_GetSoftwareVersionInformationResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&info_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&info_)) + sizeof(reason_));
+}
+
+GetSoftwareVersionInformationResponse::~GetSoftwareVersionInformationResponse() {
+  // @@protoc_insertion_point(destructor:dmi.GetSoftwareVersionInformationResponse)
+  SharedDtor();
+}
+
+void GetSoftwareVersionInformationResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete info_;
+}
+
+void GetSoftwareVersionInformationResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const GetSoftwareVersionInformationResponse& GetSoftwareVersionInformationResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_GetSoftwareVersionInformationResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void GetSoftwareVersionInformationResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.GetSoftwareVersionInformationResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && info_ != nullptr) {
+    delete info_;
+  }
+  info_ = nullptr;
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* GetSoftwareVersionInformationResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<GetSoftwareVersionInformationResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.GetSoftwareVersionInformationResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::GetSoftwareVersionInformationResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.SoftwareVersionInformation info = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::SoftwareVersionInformation::_InternalParse;
+        object = msg->mutable_info();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.GetSoftwareVersionInformationResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool GetSoftwareVersionInformationResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.GetSoftwareVersionInformationResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.GetSoftwareVersionInformationResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::GetSoftwareVersionInformationResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.SoftwareVersionInformation info = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_info()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.GetSoftwareVersionInformationResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.GetSoftwareVersionInformationResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.GetSoftwareVersionInformationResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void GetSoftwareVersionInformationResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.GetSoftwareVersionInformationResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.GetSoftwareVersionInformationResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // .dmi.SoftwareVersionInformation info = 3;
+  if (this->has_info()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, HasBitSetters::info(this), output);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetSoftwareVersionInformationResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.GetSoftwareVersionInformationResponse)
+}
+
+::google::protobuf::uint8* GetSoftwareVersionInformationResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetSoftwareVersionInformationResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.GetSoftwareVersionInformationResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // .dmi.SoftwareVersionInformation info = 3;
+  if (this->has_info()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        3, HasBitSetters::info(this), target);
+  }
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.GetSoftwareVersionInformationResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetSoftwareVersionInformationResponse)
+  return target;
+}
+
+size_t GetSoftwareVersionInformationResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.GetSoftwareVersionInformationResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 4;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.SoftwareVersionInformation info = 3;
+  if (this->has_info()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *info_);
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.GetSoftwareVersionInformationResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void GetSoftwareVersionInformationResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetSoftwareVersionInformationResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const GetSoftwareVersionInformationResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<GetSoftwareVersionInformationResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetSoftwareVersionInformationResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetSoftwareVersionInformationResponse)
+    MergeFrom(*source);
+  }
+}
+
+void GetSoftwareVersionInformationResponse::MergeFrom(const GetSoftwareVersionInformationResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetSoftwareVersionInformationResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.has_info()) {
+    mutable_info()->::dmi::SoftwareVersionInformation::MergeFrom(from.info());
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void GetSoftwareVersionInformationResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetSoftwareVersionInformationResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GetSoftwareVersionInformationResponse::CopyFrom(const GetSoftwareVersionInformationResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.GetSoftwareVersionInformationResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool GetSoftwareVersionInformationResponse::IsInitialized() const {
+  return true;
+}
+
+void GetSoftwareVersionInformationResponse::Swap(GetSoftwareVersionInformationResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void GetSoftwareVersionInformationResponse::InternalSwap(GetSoftwareVersionInformationResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(info_, other->info_);
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata GetSoftwareVersionInformationResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void DownloadImageRequest::InitAsDefaultInstance() {
+  ::dmi::_DownloadImageRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+  ::dmi::_DownloadImageRequest_default_instance_._instance.get_mutable()->image_info_ = const_cast< ::dmi::ImageInformation*>(
+      ::dmi::ImageInformation::internal_default_instance());
+}
+class DownloadImageRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const DownloadImageRequest* msg);
+  static const ::dmi::ImageInformation& image_info(const DownloadImageRequest* msg);
+};
+
+const ::dmi::Uuid&
+DownloadImageRequest::HasBitSetters::device_uuid(const DownloadImageRequest* msg) {
+  return *msg->device_uuid_;
+}
+const ::dmi::ImageInformation&
+DownloadImageRequest::HasBitSetters::image_info(const DownloadImageRequest* msg) {
+  return *msg->image_info_;
+}
+void DownloadImageRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+void DownloadImageRequest::clear_image_info() {
+  if (GetArenaNoVirtual() == nullptr && image_info_ != nullptr) {
+    delete image_info_;
+  }
+  image_info_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int DownloadImageRequest::kDeviceUuidFieldNumber;
+const int DownloadImageRequest::kImageInfoFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+DownloadImageRequest::DownloadImageRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.DownloadImageRequest)
+}
+DownloadImageRequest::DownloadImageRequest(const DownloadImageRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  if (from.has_image_info()) {
+    image_info_ = new ::dmi::ImageInformation(*from.image_info_);
+  } else {
+    image_info_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.DownloadImageRequest)
+}
+
+void DownloadImageRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_DownloadImageRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  ::memset(&device_uuid_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&image_info_) -
+      reinterpret_cast<char*>(&device_uuid_)) + sizeof(image_info_));
+}
+
+DownloadImageRequest::~DownloadImageRequest() {
+  // @@protoc_insertion_point(destructor:dmi.DownloadImageRequest)
+  SharedDtor();
+}
+
+void DownloadImageRequest::SharedDtor() {
+  if (this != internal_default_instance()) delete device_uuid_;
+  if (this != internal_default_instance()) delete image_info_;
+}
+
+void DownloadImageRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const DownloadImageRequest& DownloadImageRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_DownloadImageRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void DownloadImageRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.DownloadImageRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  if (GetArenaNoVirtual() == nullptr && image_info_ != nullptr) {
+    delete image_info_;
+  }
+  image_info_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* DownloadImageRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<DownloadImageRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // .dmi.ImageInformation image_info = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::ImageInformation::_InternalParse;
+        object = msg->mutable_image_info();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool DownloadImageRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.DownloadImageRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ImageInformation image_info = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_image_info()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.DownloadImageRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.DownloadImageRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void DownloadImageRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.DownloadImageRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // .dmi.ImageInformation image_info = 2;
+  if (this->has_image_info()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      2, HasBitSetters::image_info(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.DownloadImageRequest)
+}
+
+::google::protobuf::uint8* DownloadImageRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.DownloadImageRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // .dmi.ImageInformation image_info = 2;
+  if (this->has_image_info()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        2, HasBitSetters::image_info(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.DownloadImageRequest)
+  return target;
+}
+
+size_t DownloadImageRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.DownloadImageRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  // .dmi.ImageInformation image_info = 2;
+  if (this->has_image_info()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *image_info_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void DownloadImageRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.DownloadImageRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const DownloadImageRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<DownloadImageRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.DownloadImageRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.DownloadImageRequest)
+    MergeFrom(*source);
+  }
+}
+
+void DownloadImageRequest::MergeFrom(const DownloadImageRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.DownloadImageRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+  if (from.has_image_info()) {
+    mutable_image_info()->::dmi::ImageInformation::MergeFrom(from.image_info());
+  }
+}
+
+void DownloadImageRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.DownloadImageRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void DownloadImageRequest::CopyFrom(const DownloadImageRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.DownloadImageRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool DownloadImageRequest::IsInitialized() const {
+  return true;
+}
+
+void DownloadImageRequest::Swap(DownloadImageRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void DownloadImageRequest::InternalSwap(DownloadImageRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(device_uuid_, other->device_uuid_);
+  swap(image_info_, other->image_info_);
+}
+
+::google::protobuf::Metadata DownloadImageRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ConfigRequest::InitAsDefaultInstance() {
+  ::dmi::_ConfigRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class ConfigRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const ConfigRequest* msg);
+};
+
+const ::dmi::Uuid&
+ConfigRequest::HasBitSetters::device_uuid(const ConfigRequest* msg) {
+  return *msg->device_uuid_;
+}
+void ConfigRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ConfigRequest::kDeviceUuidFieldNumber;
+const int ConfigRequest::kConfigUrlFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ConfigRequest::ConfigRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ConfigRequest)
+}
+ConfigRequest::ConfigRequest(const ConfigRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  config_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.config_url().size() > 0) {
+    config_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.config_url_);
+  }
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.ConfigRequest)
+}
+
+void ConfigRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ConfigRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  config_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  device_uuid_ = nullptr;
+}
+
+ConfigRequest::~ConfigRequest() {
+  // @@protoc_insertion_point(destructor:dmi.ConfigRequest)
+  SharedDtor();
+}
+
+void ConfigRequest::SharedDtor() {
+  config_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete device_uuid_;
+}
+
+void ConfigRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ConfigRequest& ConfigRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ConfigRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ConfigRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ConfigRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  config_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ConfigRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ConfigRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      // string config_url = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ConfigRequest.config_url");
+        object = msg->mutable_config_url();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ConfigRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ConfigRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string config_url = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_config_url()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->config_url().data(), static_cast<int>(this->config_url().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ConfigRequest.config_url"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ConfigRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ConfigRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ConfigRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ConfigRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  // string config_url = 2;
+  if (this->config_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->config_url().data(), static_cast<int>(this->config_url().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ConfigRequest.config_url");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      2, this->config_url(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ConfigRequest)
+}
+
+::google::protobuf::uint8* ConfigRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ConfigRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  // string config_url = 2;
+  if (this->config_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->config_url().data(), static_cast<int>(this->config_url().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ConfigRequest.config_url");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->config_url(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ConfigRequest)
+  return target;
+}
+
+size_t ConfigRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ConfigRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string config_url = 2;
+  if (this->config_url().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->config_url());
+  }
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ConfigRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ConfigRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ConfigRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<ConfigRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ConfigRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ConfigRequest)
+    MergeFrom(*source);
+  }
+}
+
+void ConfigRequest::MergeFrom(const ConfigRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ConfigRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.config_url().size() > 0) {
+
+    config_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.config_url_);
+  }
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+}
+
+void ConfigRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ConfigRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ConfigRequest::CopyFrom(const ConfigRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ConfigRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ConfigRequest::IsInitialized() const {
+  return true;
+}
+
+void ConfigRequest::Swap(ConfigRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ConfigRequest::InternalSwap(ConfigRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  config_url_.Swap(&other->config_url_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(device_uuid_, other->device_uuid_);
+}
+
+::google::protobuf::Metadata ConfigRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void ConfigResponse::InitAsDefaultInstance() {
+}
+class ConfigResponse::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ConfigResponse::kStatusFieldNumber;
+const int ConfigResponse::kReasonFieldNumber;
+const int ConfigResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ConfigResponse::ConfigResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.ConfigResponse)
+}
+ConfigResponse::ConfigResponse(const ConfigResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.ConfigResponse)
+}
+
+void ConfigResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_ConfigResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+}
+
+ConfigResponse::~ConfigResponse() {
+  // @@protoc_insertion_point(destructor:dmi.ConfigResponse)
+  SharedDtor();
+}
+
+void ConfigResponse::SharedDtor() {
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void ConfigResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ConfigResponse& ConfigResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_ConfigResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ConfigResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.ConfigResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* ConfigResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<ConfigResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.ConfigResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::ConfigResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.ConfigResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool ConfigResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.ConfigResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.ConfigResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::ConfigResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.ConfigResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.ConfigResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.ConfigResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void ConfigResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.ConfigResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.ConfigResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ConfigResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.ConfigResponse)
+}
+
+::google::protobuf::uint8* ConfigResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.ConfigResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.ConfigResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.ConfigResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.ConfigResponse)
+  return target;
+}
+
+size_t ConfigResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.ConfigResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string reason_detail = 3;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.ConfigResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ConfigResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.ConfigResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ConfigResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<ConfigResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ConfigResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ConfigResponse)
+    MergeFrom(*source);
+  }
+}
+
+void ConfigResponse::MergeFrom(const ConfigResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ConfigResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void ConfigResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.ConfigResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ConfigResponse::CopyFrom(const ConfigResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ConfigResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ConfigResponse::IsInitialized() const {
+  return true;
+}
+
+void ConfigResponse::Swap(ConfigResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ConfigResponse::InternalSwap(ConfigResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata ConfigResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void StartupConfigInfoRequest::InitAsDefaultInstance() {
+  ::dmi::_StartupConfigInfoRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
+      ::dmi::Uuid::internal_default_instance());
+}
+class StartupConfigInfoRequest::HasBitSetters {
+ public:
+  static const ::dmi::Uuid& device_uuid(const StartupConfigInfoRequest* msg);
+};
+
+const ::dmi::Uuid&
+StartupConfigInfoRequest::HasBitSetters::device_uuid(const StartupConfigInfoRequest* msg) {
+  return *msg->device_uuid_;
+}
+void StartupConfigInfoRequest::clear_device_uuid() {
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+}
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int StartupConfigInfoRequest::kDeviceUuidFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+StartupConfigInfoRequest::StartupConfigInfoRequest()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.StartupConfigInfoRequest)
+}
+StartupConfigInfoRequest::StartupConfigInfoRequest(const StartupConfigInfoRequest& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_device_uuid()) {
+    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
+  } else {
+    device_uuid_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:dmi.StartupConfigInfoRequest)
+}
+
+void StartupConfigInfoRequest::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_StartupConfigInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  device_uuid_ = nullptr;
+}
+
+StartupConfigInfoRequest::~StartupConfigInfoRequest() {
+  // @@protoc_insertion_point(destructor:dmi.StartupConfigInfoRequest)
+  SharedDtor();
+}
+
+void StartupConfigInfoRequest::SharedDtor() {
+  if (this != internal_default_instance()) delete device_uuid_;
+}
+
+void StartupConfigInfoRequest::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const StartupConfigInfoRequest& StartupConfigInfoRequest::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_StartupConfigInfoRequest_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void StartupConfigInfoRequest::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.StartupConfigInfoRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
+    delete device_uuid_;
+  }
+  device_uuid_ = nullptr;
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* StartupConfigInfoRequest::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<StartupConfigInfoRequest*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        parser_till_end = ::dmi::Uuid::_InternalParse;
+        object = msg->mutable_device_uuid();
+        if (size > end - ptr) goto len_delim_till_end;
+        ptr += size;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
+            {parser_till_end, object}, ptr - size, ptr));
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool StartupConfigInfoRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.StartupConfigInfoRequest)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Uuid device_uuid = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
+               input, mutable_device_uuid()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.StartupConfigInfoRequest)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.StartupConfigInfoRequest)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void StartupConfigInfoRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.StartupConfigInfoRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      1, HasBitSetters::device_uuid(this), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.StartupConfigInfoRequest)
+}
+
+::google::protobuf::uint8* StartupConfigInfoRequest::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.StartupConfigInfoRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageToArray(
+        1, HasBitSetters::device_uuid(this), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.StartupConfigInfoRequest)
+  return target;
+}
+
+size_t StartupConfigInfoRequest::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.StartupConfigInfoRequest)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // .dmi.Uuid device_uuid = 1;
+  if (this->has_device_uuid()) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::MessageSize(
+        *device_uuid_);
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void StartupConfigInfoRequest::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.StartupConfigInfoRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  const StartupConfigInfoRequest* source =
+      ::google::protobuf::DynamicCastToGenerated<StartupConfigInfoRequest>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.StartupConfigInfoRequest)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.StartupConfigInfoRequest)
+    MergeFrom(*source);
+  }
+}
+
+void StartupConfigInfoRequest::MergeFrom(const StartupConfigInfoRequest& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.StartupConfigInfoRequest)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.has_device_uuid()) {
+    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
+  }
+}
+
+void StartupConfigInfoRequest::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.StartupConfigInfoRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void StartupConfigInfoRequest::CopyFrom(const StartupConfigInfoRequest& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.StartupConfigInfoRequest)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool StartupConfigInfoRequest::IsInitialized() const {
+  return true;
+}
+
+void StartupConfigInfoRequest::Swap(StartupConfigInfoRequest* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void StartupConfigInfoRequest::InternalSwap(StartupConfigInfoRequest* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(device_uuid_, other->device_uuid_);
+}
+
+::google::protobuf::Metadata StartupConfigInfoRequest::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// ===================================================================
+
+void StartupConfigInfoResponse::InitAsDefaultInstance() {
+}
+class StartupConfigInfoResponse::HasBitSetters {
+ public:
+};
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int StartupConfigInfoResponse::kStatusFieldNumber;
+const int StartupConfigInfoResponse::kReasonFieldNumber;
+const int StartupConfigInfoResponse::kConfigUrlFieldNumber;
+const int StartupConfigInfoResponse::kVersionFieldNumber;
+const int StartupConfigInfoResponse::kReasonDetailFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+StartupConfigInfoResponse::StartupConfigInfoResponse()
+  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:dmi.StartupConfigInfoResponse)
+}
+StartupConfigInfoResponse::StartupConfigInfoResponse(const StartupConfigInfoResponse& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(nullptr) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  config_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.config_url().size() > 0) {
+    config_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.config_url_);
+  }
+  version_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.version().size() > 0) {
+    version_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.version_);
+  }
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.reason_detail().size() > 0) {
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  ::memcpy(&status_, &from.status_,
+    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
+    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  // @@protoc_insertion_point(copy_constructor:dmi.StartupConfigInfoResponse)
+}
+
+void StartupConfigInfoResponse::SharedCtor() {
+  ::google::protobuf::internal::InitSCC(
+      &scc_info_StartupConfigInfoResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  config_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  version_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+}
+
+StartupConfigInfoResponse::~StartupConfigInfoResponse() {
+  // @@protoc_insertion_point(destructor:dmi.StartupConfigInfoResponse)
+  SharedDtor();
+}
+
+void StartupConfigInfoResponse::SharedDtor() {
+  config_url_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  version_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+void StartupConfigInfoResponse::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const StartupConfigInfoResponse& StartupConfigInfoResponse::default_instance() {
+  ::google::protobuf::internal::InitSCC(&::scc_info_StartupConfigInfoResponse_dmi_2fsw_5fmanagement_5fservice_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void StartupConfigInfoResponse::Clear() {
+// @@protoc_insertion_point(message_clear_start:dmi.StartupConfigInfoResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  config_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&status_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&reason_) -
+      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
+  _internal_metadata_.Clear();
+}
+
+#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+const char* StartupConfigInfoResponse::_InternalParse(const char* begin, const char* end, void* object,
+                  ::google::protobuf::internal::ParseContext* ctx) {
+  auto msg = static_cast<StartupConfigInfoResponse*>(object);
+  ::google::protobuf::int32 size; (void)size;
+  int depth; (void)depth;
+  ::google::protobuf::uint32 tag;
+  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
+  auto ptr = begin;
+  while (ptr < end) {
+    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
+    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+    switch (tag >> 3) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_status(static_cast<::dmi::Status>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // .dmi.StartupConfigInfoResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
+        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
+        msg->set_reason(static_cast<::dmi::StartupConfigInfoResponse_Reason>(val));
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        break;
+      }
+      // string config_url = 3;
+      case 3: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.StartupConfigInfoResponse.config_url");
+        object = msg->mutable_config_url();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string version = 4;
+      case 4: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.StartupConfigInfoResponse.version");
+        object = msg->mutable_version();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      // string reason_detail = 5;
+      case 5: {
+        if (static_cast<::google::protobuf::uint8>(tag) != 42) goto handle_unusual;
+        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
+        ctx->extra_parse_data().SetFieldName("dmi.StartupConfigInfoResponse.reason_detail");
+        object = msg->mutable_reason_detail();
+        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
+          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
+          goto string_till_end;
+        }
+        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
+        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
+        ptr += size;
+        break;
+      }
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->EndGroup(tag);
+          return ptr;
+        }
+        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
+          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
+        ptr = res.first;
+        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
+        if (res.second) return ptr;
+      }
+    }  // switch
+  }  // while
+  return ptr;
+string_till_end:
+  static_cast<::std::string*>(object)->clear();
+  static_cast<::std::string*>(object)->reserve(size);
+  goto len_delim_till_end;
+len_delim_till_end:
+  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
+                               {parser_till_end, object}, size);
+}
+#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+bool StartupConfigInfoResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:dmi.StartupConfigInfoResponse)
+  for (;;) {
+    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // .dmi.Status status = 1;
+      case 1: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_status(static_cast< ::dmi::Status >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // .dmi.StartupConfigInfoResponse.Reason reason = 2;
+      case 2: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
+          int value = 0;
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+                 input, &value)));
+          set_reason(static_cast< ::dmi::StartupConfigInfoResponse_Reason >(value));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string config_url = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_config_url()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->config_url().data(), static_cast<int>(this->config_url().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.StartupConfigInfoResponse.config_url"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string version = 4;
+      case 4: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_version()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->version().data(), static_cast<int>(this->version().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.StartupConfigInfoResponse.version"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      // string reason_detail = 5;
+      case 5: {
+        if (static_cast< ::google::protobuf::uint8>(tag) == (42 & 0xFF)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_reason_detail()));
+          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+            ::google::protobuf::internal::WireFormatLite::PARSE,
+            "dmi.StartupConfigInfoResponse.reason_detail"));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:dmi.StartupConfigInfoResponse)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:dmi.StartupConfigInfoResponse)
+  return false;
+#undef DO_
+}
+#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+
+void StartupConfigInfoResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:dmi.StartupConfigInfoResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->status(), output);
+  }
+
+  // .dmi.StartupConfigInfoResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      2, this->reason(), output);
+  }
+
+  // string config_url = 3;
+  if (this->config_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->config_url().data(), static_cast<int>(this->config_url().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.StartupConfigInfoResponse.config_url");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      3, this->config_url(), output);
+  }
+
+  // string version = 4;
+  if (this->version().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->version().data(), static_cast<int>(this->version().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.StartupConfigInfoResponse.version");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      4, this->version(), output);
+  }
+
+  // string reason_detail = 5;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.StartupConfigInfoResponse.reason_detail");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      5, this->reason_detail(), output);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:dmi.StartupConfigInfoResponse)
+}
+
+::google::protobuf::uint8* StartupConfigInfoResponse::InternalSerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // @@protoc_insertion_point(serialize_to_array_start:dmi.StartupConfigInfoResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->status(), target);
+  }
+
+  // .dmi.StartupConfigInfoResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      2, this->reason(), target);
+  }
+
+  // string config_url = 3;
+  if (this->config_url().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->config_url().data(), static_cast<int>(this->config_url().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.StartupConfigInfoResponse.config_url");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        3, this->config_url(), target);
+  }
+
+  // string version = 4;
+  if (this->version().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->version().data(), static_cast<int>(this->version().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.StartupConfigInfoResponse.version");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        4, this->version(), target);
+  }
+
+  // string reason_detail = 5;
+  if (this->reason_detail().size() > 0) {
+    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
+      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
+      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
+      "dmi.StartupConfigInfoResponse.reason_detail");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        5, this->reason_detail(), target);
+  }
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:dmi.StartupConfigInfoResponse)
+  return target;
+}
+
+size_t StartupConfigInfoResponse::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:dmi.StartupConfigInfoResponse)
+  size_t total_size = 0;
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  // string config_url = 3;
+  if (this->config_url().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->config_url());
+  }
+
+  // string version = 4;
+  if (this->version().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->version());
+  }
+
+  // string reason_detail = 5;
+  if (this->reason_detail().size() > 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::StringSize(
+        this->reason_detail());
+  }
+
+  // .dmi.Status status = 1;
+  if (this->status() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
+  }
+
+  // .dmi.StartupConfigInfoResponse.Reason reason = 2;
+  if (this->reason() != 0) {
+    total_size += 1 +
+      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void StartupConfigInfoResponse::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:dmi.StartupConfigInfoResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  const StartupConfigInfoResponse* source =
+      ::google::protobuf::DynamicCastToGenerated<StartupConfigInfoResponse>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.StartupConfigInfoResponse)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.StartupConfigInfoResponse)
+    MergeFrom(*source);
+  }
+}
+
+void StartupConfigInfoResponse::MergeFrom(const StartupConfigInfoResponse& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:dmi.StartupConfigInfoResponse)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (from.config_url().size() > 0) {
+
+    config_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.config_url_);
+  }
+  if (from.version().size() > 0) {
+
+    version_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.version_);
+  }
+  if (from.reason_detail().size() > 0) {
+
+    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
+  }
+  if (from.status() != 0) {
+    set_status(from.status());
+  }
+  if (from.reason() != 0) {
+    set_reason(from.reason());
+  }
+}
+
+void StartupConfigInfoResponse::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:dmi.StartupConfigInfoResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void StartupConfigInfoResponse::CopyFrom(const StartupConfigInfoResponse& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:dmi.StartupConfigInfoResponse)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool StartupConfigInfoResponse::IsInitialized() const {
+  return true;
+}
+
+void StartupConfigInfoResponse::Swap(StartupConfigInfoResponse* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void StartupConfigInfoResponse::InternalSwap(StartupConfigInfoResponse* other) {
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  config_url_.Swap(&other->config_url_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  version_.Swap(&other->version_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+    GetArenaNoVirtual());
+  swap(status_, other->status_);
+  swap(reason_, other->reason_);
+}
+
+::google::protobuf::Metadata StartupConfigInfoResponse::GetMetadata() const {
+  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fsw_5fmanagement_5fservice_2eproto);
+  return ::file_level_metadata_dmi_2fsw_5fmanagement_5fservice_2eproto[kIndexInFileMessages];
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> PROTOBUF_NOINLINE ::dmi::SoftwareVersionInformation* Arena::CreateMaybeMessage< ::dmi::SoftwareVersionInformation >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::SoftwareVersionInformation >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::GetSoftwareVersionInformationResponse* Arena::CreateMaybeMessage< ::dmi::GetSoftwareVersionInformationResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::GetSoftwareVersionInformationResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::DownloadImageRequest* Arena::CreateMaybeMessage< ::dmi::DownloadImageRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::DownloadImageRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ConfigRequest* Arena::CreateMaybeMessage< ::dmi::ConfigRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ConfigRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::ConfigResponse* Arena::CreateMaybeMessage< ::dmi::ConfigResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::ConfigResponse >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::StartupConfigInfoRequest* Arena::CreateMaybeMessage< ::dmi::StartupConfigInfoRequest >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::StartupConfigInfoRequest >(arena);
+}
+template<> PROTOBUF_NOINLINE ::dmi::StartupConfigInfoResponse* Arena::CreateMaybeMessage< ::dmi::StartupConfigInfoResponse >(Arena* arena) {
+  return Arena::CreateInternal< ::dmi::StartupConfigInfoResponse >(arena);
+}
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+#include <google/protobuf/port_undef.inc>
diff --git a/cpp/dmi/sw_management_service.pb.h b/cpp/dmi/sw_management_service.pb.h
new file mode 100644
index 0000000..2610c1a
--- /dev/null
+++ b/cpp/dmi/sw_management_service.pb.h
@@ -0,0 +1,1969 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/sw_management_service.proto
+
+#ifndef PROTOBUF_INCLUDED_dmi_2fsw_5fmanagement_5fservice_2eproto
+#define PROTOBUF_INCLUDED_dmi_2fsw_5fmanagement_5fservice_2eproto
+
+#include <limits>
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+#if PROTOBUF_VERSION < 3007000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3007000 < PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/port_undef.inc>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/inlined_string_field.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+#include "dmi/commons.pb.h"
+#include "dmi/hw.pb.h"
+#include "dmi/sw_image.pb.h"
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+#define PROTOBUF_INTERNAL_EXPORT_dmi_2fsw_5fmanagement_5fservice_2eproto
+
+// Internal implementation detail -- do not use these members.
+struct TableStruct_dmi_2fsw_5fmanagement_5fservice_2eproto {
+  static const ::google::protobuf::internal::ParseTableField entries[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::AuxillaryParseTableField aux[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::ParseTable schema[7]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
+  static const ::google::protobuf::uint32 offsets[];
+};
+void AddDescriptors_dmi_2fsw_5fmanagement_5fservice_2eproto();
+namespace dmi {
+class ConfigRequest;
+class ConfigRequestDefaultTypeInternal;
+extern ConfigRequestDefaultTypeInternal _ConfigRequest_default_instance_;
+class ConfigResponse;
+class ConfigResponseDefaultTypeInternal;
+extern ConfigResponseDefaultTypeInternal _ConfigResponse_default_instance_;
+class DownloadImageRequest;
+class DownloadImageRequestDefaultTypeInternal;
+extern DownloadImageRequestDefaultTypeInternal _DownloadImageRequest_default_instance_;
+class GetSoftwareVersionInformationResponse;
+class GetSoftwareVersionInformationResponseDefaultTypeInternal;
+extern GetSoftwareVersionInformationResponseDefaultTypeInternal _GetSoftwareVersionInformationResponse_default_instance_;
+class SoftwareVersionInformation;
+class SoftwareVersionInformationDefaultTypeInternal;
+extern SoftwareVersionInformationDefaultTypeInternal _SoftwareVersionInformation_default_instance_;
+class StartupConfigInfoRequest;
+class StartupConfigInfoRequestDefaultTypeInternal;
+extern StartupConfigInfoRequestDefaultTypeInternal _StartupConfigInfoRequest_default_instance_;
+class StartupConfigInfoResponse;
+class StartupConfigInfoResponseDefaultTypeInternal;
+extern StartupConfigInfoResponseDefaultTypeInternal _StartupConfigInfoResponse_default_instance_;
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> ::dmi::ConfigRequest* Arena::CreateMaybeMessage<::dmi::ConfigRequest>(Arena*);
+template<> ::dmi::ConfigResponse* Arena::CreateMaybeMessage<::dmi::ConfigResponse>(Arena*);
+template<> ::dmi::DownloadImageRequest* Arena::CreateMaybeMessage<::dmi::DownloadImageRequest>(Arena*);
+template<> ::dmi::GetSoftwareVersionInformationResponse* Arena::CreateMaybeMessage<::dmi::GetSoftwareVersionInformationResponse>(Arena*);
+template<> ::dmi::SoftwareVersionInformation* Arena::CreateMaybeMessage<::dmi::SoftwareVersionInformation>(Arena*);
+template<> ::dmi::StartupConfigInfoRequest* Arena::CreateMaybeMessage<::dmi::StartupConfigInfoRequest>(Arena*);
+template<> ::dmi::StartupConfigInfoResponse* Arena::CreateMaybeMessage<::dmi::StartupConfigInfoResponse>(Arena*);
+}  // namespace protobuf
+}  // namespace google
+namespace dmi {
+
+enum GetSoftwareVersionInformationResponse_Reason {
+  GetSoftwareVersionInformationResponse_Reason_UNDEFINED_REASON = 0,
+  GetSoftwareVersionInformationResponse_Reason_UNKNOWN_DEVICE = 1,
+  GetSoftwareVersionInformationResponse_Reason_INTERNAL_ERROR = 2,
+  GetSoftwareVersionInformationResponse_Reason_DEVICE_UNREACHABLE = 3,
+  GetSoftwareVersionInformationResponse_Reason_GetSoftwareVersionInformationResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  GetSoftwareVersionInformationResponse_Reason_GetSoftwareVersionInformationResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool GetSoftwareVersionInformationResponse_Reason_IsValid(int value);
+const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse_Reason_Reason_MIN = GetSoftwareVersionInformationResponse_Reason_UNDEFINED_REASON;
+const GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse_Reason_Reason_MAX = GetSoftwareVersionInformationResponse_Reason_DEVICE_UNREACHABLE;
+const int GetSoftwareVersionInformationResponse_Reason_Reason_ARRAYSIZE = GetSoftwareVersionInformationResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* GetSoftwareVersionInformationResponse_Reason_descriptor();
+inline const ::std::string& GetSoftwareVersionInformationResponse_Reason_Name(GetSoftwareVersionInformationResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    GetSoftwareVersionInformationResponse_Reason_descriptor(), value);
+}
+inline bool GetSoftwareVersionInformationResponse_Reason_Parse(
+    const ::std::string& name, GetSoftwareVersionInformationResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<GetSoftwareVersionInformationResponse_Reason>(
+    GetSoftwareVersionInformationResponse_Reason_descriptor(), name, value);
+}
+enum ConfigResponse_Reason {
+  ConfigResponse_Reason_UNDEFINED_REASON = 0,
+  ConfigResponse_Reason_UNKNOWN_DEVICE = 1,
+  ConfigResponse_Reason_INTERNAL_ERROR = 2,
+  ConfigResponse_Reason_ERROR_FETCHING_CONFIG = 3,
+  ConfigResponse_Reason_INVALID_CONFIG = 4,
+  ConfigResponse_Reason_OPERATION_ALREADY_IN_PROGRESS = 5,
+  ConfigResponse_Reason_DEVICE_UNREACHABLE = 6,
+  ConfigResponse_Reason_ConfigResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ConfigResponse_Reason_ConfigResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ConfigResponse_Reason_IsValid(int value);
+const ConfigResponse_Reason ConfigResponse_Reason_Reason_MIN = ConfigResponse_Reason_UNDEFINED_REASON;
+const ConfigResponse_Reason ConfigResponse_Reason_Reason_MAX = ConfigResponse_Reason_DEVICE_UNREACHABLE;
+const int ConfigResponse_Reason_Reason_ARRAYSIZE = ConfigResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ConfigResponse_Reason_descriptor();
+inline const ::std::string& ConfigResponse_Reason_Name(ConfigResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ConfigResponse_Reason_descriptor(), value);
+}
+inline bool ConfigResponse_Reason_Parse(
+    const ::std::string& name, ConfigResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ConfigResponse_Reason>(
+    ConfigResponse_Reason_descriptor(), name, value);
+}
+enum StartupConfigInfoResponse_Reason {
+  StartupConfigInfoResponse_Reason_UNDEFINED_REASON = 0,
+  StartupConfigInfoResponse_Reason_UNKNOWN_DEVICE = 1,
+  StartupConfigInfoResponse_Reason_INTERNAL_ERROR = 2,
+  StartupConfigInfoResponse_Reason_DEVICE_UNREACHABLE = 3,
+  StartupConfigInfoResponse_Reason_StartupConfigInfoResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  StartupConfigInfoResponse_Reason_StartupConfigInfoResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool StartupConfigInfoResponse_Reason_IsValid(int value);
+const StartupConfigInfoResponse_Reason StartupConfigInfoResponse_Reason_Reason_MIN = StartupConfigInfoResponse_Reason_UNDEFINED_REASON;
+const StartupConfigInfoResponse_Reason StartupConfigInfoResponse_Reason_Reason_MAX = StartupConfigInfoResponse_Reason_DEVICE_UNREACHABLE;
+const int StartupConfigInfoResponse_Reason_Reason_ARRAYSIZE = StartupConfigInfoResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* StartupConfigInfoResponse_Reason_descriptor();
+inline const ::std::string& StartupConfigInfoResponse_Reason_Name(StartupConfigInfoResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    StartupConfigInfoResponse_Reason_descriptor(), value);
+}
+inline bool StartupConfigInfoResponse_Reason_Parse(
+    const ::std::string& name, StartupConfigInfoResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<StartupConfigInfoResponse_Reason>(
+    StartupConfigInfoResponse_Reason_descriptor(), name, value);
+}
+// ===================================================================
+
+class SoftwareVersionInformation final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.SoftwareVersionInformation) */ {
+ public:
+  SoftwareVersionInformation();
+  virtual ~SoftwareVersionInformation();
+
+  SoftwareVersionInformation(const SoftwareVersionInformation& from);
+
+  inline SoftwareVersionInformation& operator=(const SoftwareVersionInformation& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  SoftwareVersionInformation(SoftwareVersionInformation&& from) noexcept
+    : SoftwareVersionInformation() {
+    *this = ::std::move(from);
+  }
+
+  inline SoftwareVersionInformation& operator=(SoftwareVersionInformation&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const SoftwareVersionInformation& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const SoftwareVersionInformation* internal_default_instance() {
+    return reinterpret_cast<const SoftwareVersionInformation*>(
+               &_SoftwareVersionInformation_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    0;
+
+  void Swap(SoftwareVersionInformation* other);
+  friend void swap(SoftwareVersionInformation& a, SoftwareVersionInformation& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline SoftwareVersionInformation* New() const final {
+    return CreateMaybeMessage<SoftwareVersionInformation>(nullptr);
+  }
+
+  SoftwareVersionInformation* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<SoftwareVersionInformation>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const SoftwareVersionInformation& from);
+  void MergeFrom(const SoftwareVersionInformation& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(SoftwareVersionInformation* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated .dmi.ImageVersion active_versions = 1;
+  int active_versions_size() const;
+  void clear_active_versions();
+  static const int kActiveVersionsFieldNumber = 1;
+  ::dmi::ImageVersion* mutable_active_versions(int index);
+  ::google::protobuf::RepeatedPtrField< ::dmi::ImageVersion >*
+      mutable_active_versions();
+  const ::dmi::ImageVersion& active_versions(int index) const;
+  ::dmi::ImageVersion* add_active_versions();
+  const ::google::protobuf::RepeatedPtrField< ::dmi::ImageVersion >&
+      active_versions() const;
+
+  // repeated .dmi.ImageVersion standby_versions = 2;
+  int standby_versions_size() const;
+  void clear_standby_versions();
+  static const int kStandbyVersionsFieldNumber = 2;
+  ::dmi::ImageVersion* mutable_standby_versions(int index);
+  ::google::protobuf::RepeatedPtrField< ::dmi::ImageVersion >*
+      mutable_standby_versions();
+  const ::dmi::ImageVersion& standby_versions(int index) const;
+  ::dmi::ImageVersion* add_standby_versions();
+  const ::google::protobuf::RepeatedPtrField< ::dmi::ImageVersion >&
+      standby_versions() const;
+
+  // @@protoc_insertion_point(class_scope:dmi.SoftwareVersionInformation)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::RepeatedPtrField< ::dmi::ImageVersion > active_versions_;
+  ::google::protobuf::RepeatedPtrField< ::dmi::ImageVersion > standby_versions_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fsw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class GetSoftwareVersionInformationResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.GetSoftwareVersionInformationResponse) */ {
+ public:
+  GetSoftwareVersionInformationResponse();
+  virtual ~GetSoftwareVersionInformationResponse();
+
+  GetSoftwareVersionInformationResponse(const GetSoftwareVersionInformationResponse& from);
+
+  inline GetSoftwareVersionInformationResponse& operator=(const GetSoftwareVersionInformationResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  GetSoftwareVersionInformationResponse(GetSoftwareVersionInformationResponse&& from) noexcept
+    : GetSoftwareVersionInformationResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline GetSoftwareVersionInformationResponse& operator=(GetSoftwareVersionInformationResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const GetSoftwareVersionInformationResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const GetSoftwareVersionInformationResponse* internal_default_instance() {
+    return reinterpret_cast<const GetSoftwareVersionInformationResponse*>(
+               &_GetSoftwareVersionInformationResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    1;
+
+  void Swap(GetSoftwareVersionInformationResponse* other);
+  friend void swap(GetSoftwareVersionInformationResponse& a, GetSoftwareVersionInformationResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline GetSoftwareVersionInformationResponse* New() const final {
+    return CreateMaybeMessage<GetSoftwareVersionInformationResponse>(nullptr);
+  }
+
+  GetSoftwareVersionInformationResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<GetSoftwareVersionInformationResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const GetSoftwareVersionInformationResponse& from);
+  void MergeFrom(const GetSoftwareVersionInformationResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(GetSoftwareVersionInformationResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef GetSoftwareVersionInformationResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    GetSoftwareVersionInformationResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    GetSoftwareVersionInformationResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    GetSoftwareVersionInformationResponse_Reason_INTERNAL_ERROR;
+  static const Reason DEVICE_UNREACHABLE =
+    GetSoftwareVersionInformationResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return GetSoftwareVersionInformationResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    GetSoftwareVersionInformationResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    GetSoftwareVersionInformationResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    GetSoftwareVersionInformationResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return GetSoftwareVersionInformationResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return GetSoftwareVersionInformationResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return GetSoftwareVersionInformationResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 4;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 4;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.SoftwareVersionInformation info = 3;
+  bool has_info() const;
+  void clear_info();
+  static const int kInfoFieldNumber = 3;
+  const ::dmi::SoftwareVersionInformation& info() const;
+  ::dmi::SoftwareVersionInformation* release_info();
+  ::dmi::SoftwareVersionInformation* mutable_info();
+  void set_allocated_info(::dmi::SoftwareVersionInformation* info);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.GetSoftwareVersionInformationResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::GetSoftwareVersionInformationResponse_Reason reason() const;
+  void set_reason(::dmi::GetSoftwareVersionInformationResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.GetSoftwareVersionInformationResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  ::dmi::SoftwareVersionInformation* info_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fsw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class DownloadImageRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.DownloadImageRequest) */ {
+ public:
+  DownloadImageRequest();
+  virtual ~DownloadImageRequest();
+
+  DownloadImageRequest(const DownloadImageRequest& from);
+
+  inline DownloadImageRequest& operator=(const DownloadImageRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  DownloadImageRequest(DownloadImageRequest&& from) noexcept
+    : DownloadImageRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline DownloadImageRequest& operator=(DownloadImageRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const DownloadImageRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const DownloadImageRequest* internal_default_instance() {
+    return reinterpret_cast<const DownloadImageRequest*>(
+               &_DownloadImageRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    2;
+
+  void Swap(DownloadImageRequest* other);
+  friend void swap(DownloadImageRequest& a, DownloadImageRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline DownloadImageRequest* New() const final {
+    return CreateMaybeMessage<DownloadImageRequest>(nullptr);
+  }
+
+  DownloadImageRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<DownloadImageRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const DownloadImageRequest& from);
+  void MergeFrom(const DownloadImageRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(DownloadImageRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // .dmi.ImageInformation image_info = 2;
+  bool has_image_info() const;
+  void clear_image_info();
+  static const int kImageInfoFieldNumber = 2;
+  const ::dmi::ImageInformation& image_info() const;
+  ::dmi::ImageInformation* release_image_info();
+  ::dmi::ImageInformation* mutable_image_info();
+  void set_allocated_image_info(::dmi::ImageInformation* image_info);
+
+  // @@protoc_insertion_point(class_scope:dmi.DownloadImageRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::Uuid* device_uuid_;
+  ::dmi::ImageInformation* image_info_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fsw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ConfigRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ConfigRequest) */ {
+ public:
+  ConfigRequest();
+  virtual ~ConfigRequest();
+
+  ConfigRequest(const ConfigRequest& from);
+
+  inline ConfigRequest& operator=(const ConfigRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ConfigRequest(ConfigRequest&& from) noexcept
+    : ConfigRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline ConfigRequest& operator=(ConfigRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ConfigRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ConfigRequest* internal_default_instance() {
+    return reinterpret_cast<const ConfigRequest*>(
+               &_ConfigRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    3;
+
+  void Swap(ConfigRequest* other);
+  friend void swap(ConfigRequest& a, ConfigRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ConfigRequest* New() const final {
+    return CreateMaybeMessage<ConfigRequest>(nullptr);
+  }
+
+  ConfigRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ConfigRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ConfigRequest& from);
+  void MergeFrom(const ConfigRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ConfigRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string config_url = 2;
+  void clear_config_url();
+  static const int kConfigUrlFieldNumber = 2;
+  const ::std::string& config_url() const;
+  void set_config_url(const ::std::string& value);
+  #if LANG_CXX11
+  void set_config_url(::std::string&& value);
+  #endif
+  void set_config_url(const char* value);
+  void set_config_url(const char* value, size_t size);
+  ::std::string* mutable_config_url();
+  ::std::string* release_config_url();
+  void set_allocated_config_url(::std::string* config_url);
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.ConfigRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr config_url_;
+  ::dmi::Uuid* device_uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fsw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ConfigResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ConfigResponse) */ {
+ public:
+  ConfigResponse();
+  virtual ~ConfigResponse();
+
+  ConfigResponse(const ConfigResponse& from);
+
+  inline ConfigResponse& operator=(const ConfigResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ConfigResponse(ConfigResponse&& from) noexcept
+    : ConfigResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline ConfigResponse& operator=(ConfigResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ConfigResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ConfigResponse* internal_default_instance() {
+    return reinterpret_cast<const ConfigResponse*>(
+               &_ConfigResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    4;
+
+  void Swap(ConfigResponse* other);
+  friend void swap(ConfigResponse& a, ConfigResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ConfigResponse* New() const final {
+    return CreateMaybeMessage<ConfigResponse>(nullptr);
+  }
+
+  ConfigResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ConfigResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ConfigResponse& from);
+  void MergeFrom(const ConfigResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ConfigResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef ConfigResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    ConfigResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    ConfigResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    ConfigResponse_Reason_INTERNAL_ERROR;
+  static const Reason ERROR_FETCHING_CONFIG =
+    ConfigResponse_Reason_ERROR_FETCHING_CONFIG;
+  static const Reason INVALID_CONFIG =
+    ConfigResponse_Reason_INVALID_CONFIG;
+  static const Reason OPERATION_ALREADY_IN_PROGRESS =
+    ConfigResponse_Reason_OPERATION_ALREADY_IN_PROGRESS;
+  static const Reason DEVICE_UNREACHABLE =
+    ConfigResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return ConfigResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    ConfigResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    ConfigResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    ConfigResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return ConfigResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return ConfigResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return ConfigResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 3;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 3;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.ConfigResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::ConfigResponse_Reason reason() const;
+  void set_reason(::dmi::ConfigResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.ConfigResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fsw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class StartupConfigInfoRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.StartupConfigInfoRequest) */ {
+ public:
+  StartupConfigInfoRequest();
+  virtual ~StartupConfigInfoRequest();
+
+  StartupConfigInfoRequest(const StartupConfigInfoRequest& from);
+
+  inline StartupConfigInfoRequest& operator=(const StartupConfigInfoRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  StartupConfigInfoRequest(StartupConfigInfoRequest&& from) noexcept
+    : StartupConfigInfoRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline StartupConfigInfoRequest& operator=(StartupConfigInfoRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const StartupConfigInfoRequest& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const StartupConfigInfoRequest* internal_default_instance() {
+    return reinterpret_cast<const StartupConfigInfoRequest*>(
+               &_StartupConfigInfoRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    5;
+
+  void Swap(StartupConfigInfoRequest* other);
+  friend void swap(StartupConfigInfoRequest& a, StartupConfigInfoRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline StartupConfigInfoRequest* New() const final {
+    return CreateMaybeMessage<StartupConfigInfoRequest>(nullptr);
+  }
+
+  StartupConfigInfoRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<StartupConfigInfoRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const StartupConfigInfoRequest& from);
+  void MergeFrom(const StartupConfigInfoRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(StartupConfigInfoRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.StartupConfigInfoRequest)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::Uuid* device_uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fsw_5fmanagement_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class StartupConfigInfoResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.StartupConfigInfoResponse) */ {
+ public:
+  StartupConfigInfoResponse();
+  virtual ~StartupConfigInfoResponse();
+
+  StartupConfigInfoResponse(const StartupConfigInfoResponse& from);
+
+  inline StartupConfigInfoResponse& operator=(const StartupConfigInfoResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  StartupConfigInfoResponse(StartupConfigInfoResponse&& from) noexcept
+    : StartupConfigInfoResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline StartupConfigInfoResponse& operator=(StartupConfigInfoResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const StartupConfigInfoResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const StartupConfigInfoResponse* internal_default_instance() {
+    return reinterpret_cast<const StartupConfigInfoResponse*>(
+               &_StartupConfigInfoResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    6;
+
+  void Swap(StartupConfigInfoResponse* other);
+  friend void swap(StartupConfigInfoResponse& a, StartupConfigInfoResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline StartupConfigInfoResponse* New() const final {
+    return CreateMaybeMessage<StartupConfigInfoResponse>(nullptr);
+  }
+
+  StartupConfigInfoResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<StartupConfigInfoResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const StartupConfigInfoResponse& from);
+  void MergeFrom(const StartupConfigInfoResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(StartupConfigInfoResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef StartupConfigInfoResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    StartupConfigInfoResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    StartupConfigInfoResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    StartupConfigInfoResponse_Reason_INTERNAL_ERROR;
+  static const Reason DEVICE_UNREACHABLE =
+    StartupConfigInfoResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return StartupConfigInfoResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    StartupConfigInfoResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    StartupConfigInfoResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    StartupConfigInfoResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return StartupConfigInfoResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return StartupConfigInfoResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return StartupConfigInfoResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string config_url = 3;
+  void clear_config_url();
+  static const int kConfigUrlFieldNumber = 3;
+  const ::std::string& config_url() const;
+  void set_config_url(const ::std::string& value);
+  #if LANG_CXX11
+  void set_config_url(::std::string&& value);
+  #endif
+  void set_config_url(const char* value);
+  void set_config_url(const char* value, size_t size);
+  ::std::string* mutable_config_url();
+  ::std::string* release_config_url();
+  void set_allocated_config_url(::std::string* config_url);
+
+  // string version = 4;
+  void clear_version();
+  static const int kVersionFieldNumber = 4;
+  const ::std::string& version() const;
+  void set_version(const ::std::string& value);
+  #if LANG_CXX11
+  void set_version(::std::string&& value);
+  #endif
+  void set_version(const char* value);
+  void set_version(const char* value, size_t size);
+  ::std::string* mutable_version();
+  ::std::string* release_version();
+  void set_allocated_version(::std::string* version);
+
+  // string reason_detail = 5;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 5;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.StartupConfigInfoResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::StartupConfigInfoResponse_Reason reason() const;
+  void set_reason(::dmi::StartupConfigInfoResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.StartupConfigInfoResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr config_url_;
+  ::google::protobuf::internal::ArenaStringPtr version_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fsw_5fmanagement_5fservice_2eproto;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// SoftwareVersionInformation
+
+// repeated .dmi.ImageVersion active_versions = 1;
+inline int SoftwareVersionInformation::active_versions_size() const {
+  return active_versions_.size();
+}
+inline ::dmi::ImageVersion* SoftwareVersionInformation::mutable_active_versions(int index) {
+  // @@protoc_insertion_point(field_mutable:dmi.SoftwareVersionInformation.active_versions)
+  return active_versions_.Mutable(index);
+}
+inline ::google::protobuf::RepeatedPtrField< ::dmi::ImageVersion >*
+SoftwareVersionInformation::mutable_active_versions() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.SoftwareVersionInformation.active_versions)
+  return &active_versions_;
+}
+inline const ::dmi::ImageVersion& SoftwareVersionInformation::active_versions(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.SoftwareVersionInformation.active_versions)
+  return active_versions_.Get(index);
+}
+inline ::dmi::ImageVersion* SoftwareVersionInformation::add_active_versions() {
+  // @@protoc_insertion_point(field_add:dmi.SoftwareVersionInformation.active_versions)
+  return active_versions_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::dmi::ImageVersion >&
+SoftwareVersionInformation::active_versions() const {
+  // @@protoc_insertion_point(field_list:dmi.SoftwareVersionInformation.active_versions)
+  return active_versions_;
+}
+
+// repeated .dmi.ImageVersion standby_versions = 2;
+inline int SoftwareVersionInformation::standby_versions_size() const {
+  return standby_versions_.size();
+}
+inline ::dmi::ImageVersion* SoftwareVersionInformation::mutable_standby_versions(int index) {
+  // @@protoc_insertion_point(field_mutable:dmi.SoftwareVersionInformation.standby_versions)
+  return standby_versions_.Mutable(index);
+}
+inline ::google::protobuf::RepeatedPtrField< ::dmi::ImageVersion >*
+SoftwareVersionInformation::mutable_standby_versions() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.SoftwareVersionInformation.standby_versions)
+  return &standby_versions_;
+}
+inline const ::dmi::ImageVersion& SoftwareVersionInformation::standby_versions(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.SoftwareVersionInformation.standby_versions)
+  return standby_versions_.Get(index);
+}
+inline ::dmi::ImageVersion* SoftwareVersionInformation::add_standby_versions() {
+  // @@protoc_insertion_point(field_add:dmi.SoftwareVersionInformation.standby_versions)
+  return standby_versions_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::dmi::ImageVersion >&
+SoftwareVersionInformation::standby_versions() const {
+  // @@protoc_insertion_point(field_list:dmi.SoftwareVersionInformation.standby_versions)
+  return standby_versions_;
+}
+
+// -------------------------------------------------------------------
+
+// GetSoftwareVersionInformationResponse
+
+// .dmi.Status status = 1;
+inline void GetSoftwareVersionInformationResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status GetSoftwareVersionInformationResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.GetSoftwareVersionInformationResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void GetSoftwareVersionInformationResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.GetSoftwareVersionInformationResponse.status)
+}
+
+// .dmi.GetSoftwareVersionInformationResponse.Reason reason = 2;
+inline void GetSoftwareVersionInformationResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::GetSoftwareVersionInformationResponse_Reason GetSoftwareVersionInformationResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.GetSoftwareVersionInformationResponse.reason)
+  return static_cast< ::dmi::GetSoftwareVersionInformationResponse_Reason >(reason_);
+}
+inline void GetSoftwareVersionInformationResponse::set_reason(::dmi::GetSoftwareVersionInformationResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.GetSoftwareVersionInformationResponse.reason)
+}
+
+// .dmi.SoftwareVersionInformation info = 3;
+inline bool GetSoftwareVersionInformationResponse::has_info() const {
+  return this != internal_default_instance() && info_ != nullptr;
+}
+inline void GetSoftwareVersionInformationResponse::clear_info() {
+  if (GetArenaNoVirtual() == nullptr && info_ != nullptr) {
+    delete info_;
+  }
+  info_ = nullptr;
+}
+inline const ::dmi::SoftwareVersionInformation& GetSoftwareVersionInformationResponse::info() const {
+  const ::dmi::SoftwareVersionInformation* p = info_;
+  // @@protoc_insertion_point(field_get:dmi.GetSoftwareVersionInformationResponse.info)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::SoftwareVersionInformation*>(
+      &::dmi::_SoftwareVersionInformation_default_instance_);
+}
+inline ::dmi::SoftwareVersionInformation* GetSoftwareVersionInformationResponse::release_info() {
+  // @@protoc_insertion_point(field_release:dmi.GetSoftwareVersionInformationResponse.info)
+  
+  ::dmi::SoftwareVersionInformation* temp = info_;
+  info_ = nullptr;
+  return temp;
+}
+inline ::dmi::SoftwareVersionInformation* GetSoftwareVersionInformationResponse::mutable_info() {
+  
+  if (info_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::SoftwareVersionInformation>(GetArenaNoVirtual());
+    info_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.GetSoftwareVersionInformationResponse.info)
+  return info_;
+}
+inline void GetSoftwareVersionInformationResponse::set_allocated_info(::dmi::SoftwareVersionInformation* info) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete info_;
+  }
+  if (info) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      info = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, info, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  info_ = info;
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetSoftwareVersionInformationResponse.info)
+}
+
+// string reason_detail = 4;
+inline void GetSoftwareVersionInformationResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& GetSoftwareVersionInformationResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.GetSoftwareVersionInformationResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void GetSoftwareVersionInformationResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.GetSoftwareVersionInformationResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void GetSoftwareVersionInformationResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.GetSoftwareVersionInformationResponse.reason_detail)
+}
+#endif
+inline void GetSoftwareVersionInformationResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.GetSoftwareVersionInformationResponse.reason_detail)
+}
+inline void GetSoftwareVersionInformationResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.GetSoftwareVersionInformationResponse.reason_detail)
+}
+inline ::std::string* GetSoftwareVersionInformationResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.GetSoftwareVersionInformationResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* GetSoftwareVersionInformationResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.GetSoftwareVersionInformationResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void GetSoftwareVersionInformationResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.GetSoftwareVersionInformationResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// DownloadImageRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool DownloadImageRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& DownloadImageRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.DownloadImageRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* DownloadImageRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.DownloadImageRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* DownloadImageRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.DownloadImageRequest.device_uuid)
+  return device_uuid_;
+}
+inline void DownloadImageRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.DownloadImageRequest.device_uuid)
+}
+
+// .dmi.ImageInformation image_info = 2;
+inline bool DownloadImageRequest::has_image_info() const {
+  return this != internal_default_instance() && image_info_ != nullptr;
+}
+inline const ::dmi::ImageInformation& DownloadImageRequest::image_info() const {
+  const ::dmi::ImageInformation* p = image_info_;
+  // @@protoc_insertion_point(field_get:dmi.DownloadImageRequest.image_info)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ImageInformation*>(
+      &::dmi::_ImageInformation_default_instance_);
+}
+inline ::dmi::ImageInformation* DownloadImageRequest::release_image_info() {
+  // @@protoc_insertion_point(field_release:dmi.DownloadImageRequest.image_info)
+  
+  ::dmi::ImageInformation* temp = image_info_;
+  image_info_ = nullptr;
+  return temp;
+}
+inline ::dmi::ImageInformation* DownloadImageRequest::mutable_image_info() {
+  
+  if (image_info_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ImageInformation>(GetArenaNoVirtual());
+    image_info_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.DownloadImageRequest.image_info)
+  return image_info_;
+}
+inline void DownloadImageRequest::set_allocated_image_info(::dmi::ImageInformation* image_info) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(image_info_);
+  }
+  if (image_info) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      image_info = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, image_info, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  image_info_ = image_info;
+  // @@protoc_insertion_point(field_set_allocated:dmi.DownloadImageRequest.image_info)
+}
+
+// -------------------------------------------------------------------
+
+// ConfigRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool ConfigRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& ConfigRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.ConfigRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* ConfigRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.ConfigRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* ConfigRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ConfigRequest.device_uuid)
+  return device_uuid_;
+}
+inline void ConfigRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ConfigRequest.device_uuid)
+}
+
+// string config_url = 2;
+inline void ConfigRequest::clear_config_url() {
+  config_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ConfigRequest::config_url() const {
+  // @@protoc_insertion_point(field_get:dmi.ConfigRequest.config_url)
+  return config_url_.GetNoArena();
+}
+inline void ConfigRequest::set_config_url(const ::std::string& value) {
+  
+  config_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ConfigRequest.config_url)
+}
+#if LANG_CXX11
+inline void ConfigRequest::set_config_url(::std::string&& value) {
+  
+  config_url_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ConfigRequest.config_url)
+}
+#endif
+inline void ConfigRequest::set_config_url(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  config_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ConfigRequest.config_url)
+}
+inline void ConfigRequest::set_config_url(const char* value, size_t size) {
+  
+  config_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ConfigRequest.config_url)
+}
+inline ::std::string* ConfigRequest::mutable_config_url() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ConfigRequest.config_url)
+  return config_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ConfigRequest::release_config_url() {
+  // @@protoc_insertion_point(field_release:dmi.ConfigRequest.config_url)
+  
+  return config_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ConfigRequest::set_allocated_config_url(::std::string* config_url) {
+  if (config_url != nullptr) {
+    
+  } else {
+    
+  }
+  config_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), config_url);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ConfigRequest.config_url)
+}
+
+// -------------------------------------------------------------------
+
+// ConfigResponse
+
+// .dmi.Status status = 1;
+inline void ConfigResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status ConfigResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.ConfigResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void ConfigResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ConfigResponse.status)
+}
+
+// .dmi.ConfigResponse.Reason reason = 2;
+inline void ConfigResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::ConfigResponse_Reason ConfigResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.ConfigResponse.reason)
+  return static_cast< ::dmi::ConfigResponse_Reason >(reason_);
+}
+inline void ConfigResponse::set_reason(::dmi::ConfigResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ConfigResponse.reason)
+}
+
+// string reason_detail = 3;
+inline void ConfigResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ConfigResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.ConfigResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void ConfigResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ConfigResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void ConfigResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ConfigResponse.reason_detail)
+}
+#endif
+inline void ConfigResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ConfigResponse.reason_detail)
+}
+inline void ConfigResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ConfigResponse.reason_detail)
+}
+inline ::std::string* ConfigResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ConfigResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ConfigResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.ConfigResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ConfigResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ConfigResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// StartupConfigInfoRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool StartupConfigInfoRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& StartupConfigInfoRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.StartupConfigInfoRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* StartupConfigInfoRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.StartupConfigInfoRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* StartupConfigInfoRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.StartupConfigInfoRequest.device_uuid)
+  return device_uuid_;
+}
+inline void StartupConfigInfoRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.StartupConfigInfoRequest.device_uuid)
+}
+
+// -------------------------------------------------------------------
+
+// StartupConfigInfoResponse
+
+// .dmi.Status status = 1;
+inline void StartupConfigInfoResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status StartupConfigInfoResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.StartupConfigInfoResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void StartupConfigInfoResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.StartupConfigInfoResponse.status)
+}
+
+// .dmi.StartupConfigInfoResponse.Reason reason = 2;
+inline void StartupConfigInfoResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::StartupConfigInfoResponse_Reason StartupConfigInfoResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.StartupConfigInfoResponse.reason)
+  return static_cast< ::dmi::StartupConfigInfoResponse_Reason >(reason_);
+}
+inline void StartupConfigInfoResponse::set_reason(::dmi::StartupConfigInfoResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.StartupConfigInfoResponse.reason)
+}
+
+// string config_url = 3;
+inline void StartupConfigInfoResponse::clear_config_url() {
+  config_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& StartupConfigInfoResponse::config_url() const {
+  // @@protoc_insertion_point(field_get:dmi.StartupConfigInfoResponse.config_url)
+  return config_url_.GetNoArena();
+}
+inline void StartupConfigInfoResponse::set_config_url(const ::std::string& value) {
+  
+  config_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.StartupConfigInfoResponse.config_url)
+}
+#if LANG_CXX11
+inline void StartupConfigInfoResponse::set_config_url(::std::string&& value) {
+  
+  config_url_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.StartupConfigInfoResponse.config_url)
+}
+#endif
+inline void StartupConfigInfoResponse::set_config_url(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  config_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.StartupConfigInfoResponse.config_url)
+}
+inline void StartupConfigInfoResponse::set_config_url(const char* value, size_t size) {
+  
+  config_url_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.StartupConfigInfoResponse.config_url)
+}
+inline ::std::string* StartupConfigInfoResponse::mutable_config_url() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.StartupConfigInfoResponse.config_url)
+  return config_url_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* StartupConfigInfoResponse::release_config_url() {
+  // @@protoc_insertion_point(field_release:dmi.StartupConfigInfoResponse.config_url)
+  
+  return config_url_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void StartupConfigInfoResponse::set_allocated_config_url(::std::string* config_url) {
+  if (config_url != nullptr) {
+    
+  } else {
+    
+  }
+  config_url_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), config_url);
+  // @@protoc_insertion_point(field_set_allocated:dmi.StartupConfigInfoResponse.config_url)
+}
+
+// string version = 4;
+inline void StartupConfigInfoResponse::clear_version() {
+  version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& StartupConfigInfoResponse::version() const {
+  // @@protoc_insertion_point(field_get:dmi.StartupConfigInfoResponse.version)
+  return version_.GetNoArena();
+}
+inline void StartupConfigInfoResponse::set_version(const ::std::string& value) {
+  
+  version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.StartupConfigInfoResponse.version)
+}
+#if LANG_CXX11
+inline void StartupConfigInfoResponse::set_version(::std::string&& value) {
+  
+  version_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.StartupConfigInfoResponse.version)
+}
+#endif
+inline void StartupConfigInfoResponse::set_version(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.StartupConfigInfoResponse.version)
+}
+inline void StartupConfigInfoResponse::set_version(const char* value, size_t size) {
+  
+  version_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.StartupConfigInfoResponse.version)
+}
+inline ::std::string* StartupConfigInfoResponse::mutable_version() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.StartupConfigInfoResponse.version)
+  return version_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* StartupConfigInfoResponse::release_version() {
+  // @@protoc_insertion_point(field_release:dmi.StartupConfigInfoResponse.version)
+  
+  return version_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void StartupConfigInfoResponse::set_allocated_version(::std::string* version) {
+  if (version != nullptr) {
+    
+  } else {
+    
+  }
+  version_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), version);
+  // @@protoc_insertion_point(field_set_allocated:dmi.StartupConfigInfoResponse.version)
+}
+
+// string reason_detail = 5;
+inline void StartupConfigInfoResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& StartupConfigInfoResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.StartupConfigInfoResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void StartupConfigInfoResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.StartupConfigInfoResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void StartupConfigInfoResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.StartupConfigInfoResponse.reason_detail)
+}
+#endif
+inline void StartupConfigInfoResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.StartupConfigInfoResponse.reason_detail)
+}
+inline void StartupConfigInfoResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.StartupConfigInfoResponse.reason_detail)
+}
+inline ::std::string* StartupConfigInfoResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.StartupConfigInfoResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* StartupConfigInfoResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.StartupConfigInfoResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void StartupConfigInfoResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.StartupConfigInfoResponse.reason_detail)
+}
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace dmi
+
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::dmi::GetSoftwareVersionInformationResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::GetSoftwareVersionInformationResponse_Reason>() {
+  return ::dmi::GetSoftwareVersionInformationResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::ConfigResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ConfigResponse_Reason>() {
+  return ::dmi::ConfigResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::StartupConfigInfoResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::StartupConfigInfoResponse_Reason>() {
+  return ::dmi::StartupConfigInfoResponse_Reason_descriptor();
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#include <google/protobuf/port_undef.inc>
+#endif  // PROTOBUF_INCLUDED_dmi_2fsw_5fmanagement_5fservice_2eproto
