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>
