diff --git a/cpp/dmi/hw_events_mgmt_service.pb.h b/cpp/dmi/hw_events_mgmt_service.pb.h
new file mode 100644
index 0000000..472a6a9
--- /dev/null
+++ b/cpp/dmi/hw_events_mgmt_service.pb.h
@@ -0,0 +1,3099 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: dmi/hw_events_mgmt_service.proto
+
+#ifndef PROTOBUF_INCLUDED_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto
+#define PROTOBUF_INCLUDED_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto
+
+#include <limits>
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+#if PROTOBUF_VERSION < 3007000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3007000 < PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/port_undef.inc>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/inlined_string_field.h>
+#include <google/protobuf/metadata.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+#include "dmi/commons.pb.h"
+#include "dmi/hw.pb.h"
+#include <google/protobuf/timestamp.pb.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+#define PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto
+
+// Internal implementation detail -- do not use these members.
+struct TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto {
+  static const ::google::protobuf::internal::ParseTableField entries[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::AuxillaryParseTableField aux[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::ParseTable schema[11]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
+  static const ::google::protobuf::uint32 offsets[];
+};
+void AddDescriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto();
+namespace dmi {
+class Event;
+class EventDefaultTypeInternal;
+extern EventDefaultTypeInternal _Event_default_instance_;
+class EventCfg;
+class EventCfgDefaultTypeInternal;
+extern EventCfgDefaultTypeInternal _EventCfg_default_instance_;
+class EventMetaData;
+class EventMetaDataDefaultTypeInternal;
+extern EventMetaDataDefaultTypeInternal _EventMetaData_default_instance_;
+class EventsCfg;
+class EventsCfgDefaultTypeInternal;
+extern EventsCfgDefaultTypeInternal _EventsCfg_default_instance_;
+class EventsConfigurationRequest;
+class EventsConfigurationRequestDefaultTypeInternal;
+extern EventsConfigurationRequestDefaultTypeInternal _EventsConfigurationRequest_default_instance_;
+class EventsConfigurationResponse;
+class EventsConfigurationResponseDefaultTypeInternal;
+extern EventsConfigurationResponseDefaultTypeInternal _EventsConfigurationResponse_default_instance_;
+class ListEventsResponse;
+class ListEventsResponseDefaultTypeInternal;
+extern ListEventsResponseDefaultTypeInternal _ListEventsResponse_default_instance_;
+class ThresholdInformation;
+class ThresholdInformationDefaultTypeInternal;
+extern ThresholdInformationDefaultTypeInternal _ThresholdInformation_default_instance_;
+class Thresholds;
+class ThresholdsDefaultTypeInternal;
+extern ThresholdsDefaultTypeInternal _Thresholds_default_instance_;
+class ValueType;
+class ValueTypeDefaultTypeInternal;
+extern ValueTypeDefaultTypeInternal _ValueType_default_instance_;
+class WaterMarks;
+class WaterMarksDefaultTypeInternal;
+extern WaterMarksDefaultTypeInternal _WaterMarks_default_instance_;
+}  // namespace dmi
+namespace google {
+namespace protobuf {
+template<> ::dmi::Event* Arena::CreateMaybeMessage<::dmi::Event>(Arena*);
+template<> ::dmi::EventCfg* Arena::CreateMaybeMessage<::dmi::EventCfg>(Arena*);
+template<> ::dmi::EventMetaData* Arena::CreateMaybeMessage<::dmi::EventMetaData>(Arena*);
+template<> ::dmi::EventsCfg* Arena::CreateMaybeMessage<::dmi::EventsCfg>(Arena*);
+template<> ::dmi::EventsConfigurationRequest* Arena::CreateMaybeMessage<::dmi::EventsConfigurationRequest>(Arena*);
+template<> ::dmi::EventsConfigurationResponse* Arena::CreateMaybeMessage<::dmi::EventsConfigurationResponse>(Arena*);
+template<> ::dmi::ListEventsResponse* Arena::CreateMaybeMessage<::dmi::ListEventsResponse>(Arena*);
+template<> ::dmi::ThresholdInformation* Arena::CreateMaybeMessage<::dmi::ThresholdInformation>(Arena*);
+template<> ::dmi::Thresholds* Arena::CreateMaybeMessage<::dmi::Thresholds>(Arena*);
+template<> ::dmi::ValueType* Arena::CreateMaybeMessage<::dmi::ValueType>(Arena*);
+template<> ::dmi::WaterMarks* Arena::CreateMaybeMessage<::dmi::WaterMarks>(Arena*);
+}  // namespace protobuf
+}  // namespace google
+namespace dmi {
+
+enum ListEventsResponse_Reason {
+  ListEventsResponse_Reason_UNDEFINED_REASON = 0,
+  ListEventsResponse_Reason_UNKNOWN_DEVICE = 1,
+  ListEventsResponse_Reason_INTERNAL_ERROR = 2,
+  ListEventsResponse_Reason_DEVICE_UNREACHABLE = 3,
+  ListEventsResponse_Reason_ListEventsResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  ListEventsResponse_Reason_ListEventsResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool ListEventsResponse_Reason_IsValid(int value);
+const ListEventsResponse_Reason ListEventsResponse_Reason_Reason_MIN = ListEventsResponse_Reason_UNDEFINED_REASON;
+const ListEventsResponse_Reason ListEventsResponse_Reason_Reason_MAX = ListEventsResponse_Reason_DEVICE_UNREACHABLE;
+const int ListEventsResponse_Reason_Reason_ARRAYSIZE = ListEventsResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* ListEventsResponse_Reason_descriptor();
+inline const ::std::string& ListEventsResponse_Reason_Name(ListEventsResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    ListEventsResponse_Reason_descriptor(), value);
+}
+inline bool ListEventsResponse_Reason_Parse(
+    const ::std::string& name, ListEventsResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<ListEventsResponse_Reason>(
+    ListEventsResponse_Reason_descriptor(), name, value);
+}
+enum EventsConfigurationResponse_Reason {
+  EventsConfigurationResponse_Reason_UNDEFINED_REASON = 0,
+  EventsConfigurationResponse_Reason_UNKNOWN_DEVICE = 1,
+  EventsConfigurationResponse_Reason_INTERNAL_ERROR = 2,
+  EventsConfigurationResponse_Reason_INVALID_CONFIG = 3,
+  EventsConfigurationResponse_Reason_DEVICE_UNREACHABLE = 4,
+  EventsConfigurationResponse_Reason_EventsConfigurationResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  EventsConfigurationResponse_Reason_EventsConfigurationResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool EventsConfigurationResponse_Reason_IsValid(int value);
+const EventsConfigurationResponse_Reason EventsConfigurationResponse_Reason_Reason_MIN = EventsConfigurationResponse_Reason_UNDEFINED_REASON;
+const EventsConfigurationResponse_Reason EventsConfigurationResponse_Reason_Reason_MAX = EventsConfigurationResponse_Reason_DEVICE_UNREACHABLE;
+const int EventsConfigurationResponse_Reason_Reason_ARRAYSIZE = EventsConfigurationResponse_Reason_Reason_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* EventsConfigurationResponse_Reason_descriptor();
+inline const ::std::string& EventsConfigurationResponse_Reason_Name(EventsConfigurationResponse_Reason value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    EventsConfigurationResponse_Reason_descriptor(), value);
+}
+inline bool EventsConfigurationResponse_Reason_Parse(
+    const ::std::string& name, EventsConfigurationResponse_Reason* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<EventsConfigurationResponse_Reason>(
+    EventsConfigurationResponse_Reason_descriptor(), name, value);
+}
+enum EventIds {
+  EVENT_NAME_UNDEFINED = 0,
+  EVENT_TRANSCEIVER_PLUG_OUT = 100,
+  EVENT_TRANSCEIVER_PLUG_IN = 101,
+  EVENT_TRANSCEIVER_VOLTAGE_ABOVE_THRESHOLD = 102,
+  EVENT_TRANSCEIVER_VOLTAGE_BELOW_THRESHOLD = 103,
+  EVENT_TRANSCEIVER_TEMPERATURE_ABOVE_THRESHOLD = 104,
+  EVENT_TRANSCEIVER_TEMPERATURE_BELOW_THRESHOLD = 105,
+  EVENT_TRANSCEIVER_CURRENT_ABOVE_THRESHOLD = 106,
+  EVENT_TRANSCEIVER_CURRENT_BELOW_THRESHOLD = 107,
+  EVENT_TRANSCEIVER_RX_POWER_ABOVE_THRESHOLD = 108,
+  EVENT_TRANSCEIVER_RX_POWER_BELOW_THRESHOLD = 109,
+  EVENT_TRANSCEIVER_TX_POWER_ABOVE_THRESHOLD = 110,
+  EVENT_TRANSCEIVER_TX_POWER_BELOW_THRESHOLD = 111,
+  EVENT_TRANSCEIVER_FAILURE = 112,
+  EVENT_TRANSCEIVER_VOLTAGE_ABOVE_THRESHOLD_RECOVERED = 113,
+  EVENT_TRANSCEIVER_VOLTAGE_BELOW_THRESHOLD_RECOVERED = 114,
+  EVENT_TRANSCEIVER_TEMPERATURE_ABOVE_THRESHOLD_RECOVERED = 115,
+  EVENT_TRANSCEIVER_TEMPERATURE_BELOW_THRESHOLD_RECOVERED = 116,
+  EVENT_TRANSCEIVER_CURRENT_ABOVE_THRESHOLD_RECOVERED = 117,
+  EVENT_TRANSCEIVER_CURRENT_BELOW_THRESHOLD_RECOVERED = 118,
+  EVENT_TRANSCEIVER_RX_POWER_ABOVE_THRESHOLD_RECOVERED = 119,
+  EVENT_TRANSCEIVER_RX_POWER_BELOW_THRESHOLD_RECOVERED = 120,
+  EVENT_TRANSCEIVER_TX_POWER_ABOVE_THRESHOLD_RECOVERED = 121,
+  EVENT_TRANSCEIVER_TX_POWER_BELOW_THRESHOLD_RECOVERED = 122,
+  EVENT_TRANSCEIVER_FAILURE_RECOVERED = 123,
+  EVENT_PSU_PLUG_OUT = 200,
+  EVENT_PSU_PLUG_IN = 201,
+  EVENT_PSU_FAILURE = 202,
+  EVENT_PSU_FAILURE_RECOVERED = 203,
+  EVENT_FAN_FAILURE = 300,
+  EVENT_FAN_PLUG_OUT = 301,
+  EVENT_FAN_PLUG_IN = 302,
+  EVENT_FAN_FAILURE_RECOVERED = 303,
+  EVENT_CPU_TEMPERATURE_ABOVE_CRITICAL = 400,
+  EVENT_CPU_TEMPERATURE_ABOVE_FATAL = 401,
+  EVENT_CPU_TEMPERATURE_ABOVE_CRITICAL_RECOVERED = 402,
+  EVENT_CPU_TEMPERATURE_ABOVE_FATAL_RECOVERED = 403,
+  EVENT_HW_DEVICE_RESET = 500,
+  EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL = 501,
+  EVENT_HW_DEVICE_TEMPERATURE_ABOVE_FATAL = 502,
+  EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL_RECOVERED = 503,
+  EVENT_HW_DEVICE_TEMPERATURE_ABOVE_FATAL_RECOVERED = 504,
+  EventIds_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
+  EventIds_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
+};
+bool EventIds_IsValid(int value);
+const EventIds EventIds_MIN = EVENT_NAME_UNDEFINED;
+const EventIds EventIds_MAX = EVENT_HW_DEVICE_TEMPERATURE_ABOVE_FATAL_RECOVERED;
+const int EventIds_ARRAYSIZE = EventIds_MAX + 1;
+
+const ::google::protobuf::EnumDescriptor* EventIds_descriptor();
+inline const ::std::string& EventIds_Name(EventIds value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    EventIds_descriptor(), value);
+}
+inline bool EventIds_Parse(
+    const ::std::string& name, EventIds* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<EventIds>(
+    EventIds_descriptor(), name, value);
+}
+// ===================================================================
+
+class ValueType final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ValueType) */ {
+ public:
+  ValueType();
+  virtual ~ValueType();
+
+  ValueType(const ValueType& from);
+
+  inline ValueType& operator=(const ValueType& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ValueType(ValueType&& from) noexcept
+    : ValueType() {
+    *this = ::std::move(from);
+  }
+
+  inline ValueType& operator=(ValueType&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ValueType& default_instance();
+
+  enum ValCase {
+    kIntVal = 1,
+    kUintVal = 2,
+    kFloatVal = 3,
+    VAL_NOT_SET = 0,
+  };
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ValueType* internal_default_instance() {
+    return reinterpret_cast<const ValueType*>(
+               &_ValueType_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    0;
+
+  void Swap(ValueType* other);
+  friend void swap(ValueType& a, ValueType& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ValueType* New() const final {
+    return CreateMaybeMessage<ValueType>(nullptr);
+  }
+
+  ValueType* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ValueType>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ValueType& from);
+  void MergeFrom(const ValueType& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ValueType* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // int64 int_val = 1;
+  private:
+  bool has_int_val() const;
+  public:
+  void clear_int_val();
+  static const int kIntValFieldNumber = 1;
+  ::google::protobuf::int64 int_val() const;
+  void set_int_val(::google::protobuf::int64 value);
+
+  // uint64 uint_val = 2;
+  private:
+  bool has_uint_val() const;
+  public:
+  void clear_uint_val();
+  static const int kUintValFieldNumber = 2;
+  ::google::protobuf::uint64 uint_val() const;
+  void set_uint_val(::google::protobuf::uint64 value);
+
+  // float float_val = 3;
+  private:
+  bool has_float_val() const;
+  public:
+  void clear_float_val();
+  static const int kFloatValFieldNumber = 3;
+  float float_val() const;
+  void set_float_val(float value);
+
+  void clear_val();
+  ValCase val_case() const;
+  // @@protoc_insertion_point(class_scope:dmi.ValueType)
+ private:
+  class HasBitSetters;
+  void set_has_int_val();
+  void set_has_uint_val();
+  void set_has_float_val();
+
+  inline bool has_val() const;
+  inline void clear_has_val();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  union ValUnion {
+    ValUnion() {}
+    ::google::protobuf::int64 int_val_;
+    ::google::protobuf::uint64 uint_val_;
+    float float_val_;
+  } val_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  ::google::protobuf::uint32 _oneof_case_[1];
+
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class WaterMarks final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.WaterMarks) */ {
+ public:
+  WaterMarks();
+  virtual ~WaterMarks();
+
+  WaterMarks(const WaterMarks& from);
+
+  inline WaterMarks& operator=(const WaterMarks& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  WaterMarks(WaterMarks&& from) noexcept
+    : WaterMarks() {
+    *this = ::std::move(from);
+  }
+
+  inline WaterMarks& operator=(WaterMarks&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const WaterMarks& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const WaterMarks* internal_default_instance() {
+    return reinterpret_cast<const WaterMarks*>(
+               &_WaterMarks_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    1;
+
+  void Swap(WaterMarks* other);
+  friend void swap(WaterMarks& a, WaterMarks& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline WaterMarks* New() const final {
+    return CreateMaybeMessage<WaterMarks>(nullptr);
+  }
+
+  WaterMarks* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<WaterMarks>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const WaterMarks& from);
+  void MergeFrom(const WaterMarks& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(WaterMarks* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.ValueType high = 1;
+  bool has_high() const;
+  void clear_high();
+  static const int kHighFieldNumber = 1;
+  const ::dmi::ValueType& high() const;
+  ::dmi::ValueType* release_high();
+  ::dmi::ValueType* mutable_high();
+  void set_allocated_high(::dmi::ValueType* high);
+
+  // .dmi.ValueType low = 2;
+  bool has_low() const;
+  void clear_low();
+  static const int kLowFieldNumber = 2;
+  const ::dmi::ValueType& low() const;
+  ::dmi::ValueType* release_low();
+  ::dmi::ValueType* mutable_low();
+  void set_allocated_low(::dmi::ValueType* low);
+
+  // @@protoc_insertion_point(class_scope:dmi.WaterMarks)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::ValueType* high_;
+  ::dmi::ValueType* low_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class Thresholds final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.Thresholds) */ {
+ public:
+  Thresholds();
+  virtual ~Thresholds();
+
+  Thresholds(const Thresholds& from);
+
+  inline Thresholds& operator=(const Thresholds& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Thresholds(Thresholds&& from) noexcept
+    : Thresholds() {
+    *this = ::std::move(from);
+  }
+
+  inline Thresholds& operator=(Thresholds&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const Thresholds& default_instance();
+
+  enum ThresholdCase {
+    kUpper = 1,
+    kLower = 2,
+    THRESHOLD_NOT_SET = 0,
+  };
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Thresholds* internal_default_instance() {
+    return reinterpret_cast<const Thresholds*>(
+               &_Thresholds_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    2;
+
+  void Swap(Thresholds* other);
+  friend void swap(Thresholds& a, Thresholds& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Thresholds* New() const final {
+    return CreateMaybeMessage<Thresholds>(nullptr);
+  }
+
+  Thresholds* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<Thresholds>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const Thresholds& from);
+  void MergeFrom(const Thresholds& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Thresholds* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.WaterMarks upper = 1;
+  bool has_upper() const;
+  void clear_upper();
+  static const int kUpperFieldNumber = 1;
+  const ::dmi::WaterMarks& upper() const;
+  ::dmi::WaterMarks* release_upper();
+  ::dmi::WaterMarks* mutable_upper();
+  void set_allocated_upper(::dmi::WaterMarks* upper);
+
+  // .dmi.WaterMarks lower = 2;
+  bool has_lower() const;
+  void clear_lower();
+  static const int kLowerFieldNumber = 2;
+  const ::dmi::WaterMarks& lower() const;
+  ::dmi::WaterMarks* release_lower();
+  ::dmi::WaterMarks* mutable_lower();
+  void set_allocated_lower(::dmi::WaterMarks* lower);
+
+  void clear_threshold();
+  ThresholdCase threshold_case() const;
+  // @@protoc_insertion_point(class_scope:dmi.Thresholds)
+ private:
+  class HasBitSetters;
+  void set_has_upper();
+  void set_has_lower();
+
+  inline bool has_threshold() const;
+  inline void clear_has_threshold();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  union ThresholdUnion {
+    ThresholdUnion() {}
+    ::dmi::WaterMarks* upper_;
+    ::dmi::WaterMarks* lower_;
+  } threshold_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  ::google::protobuf::uint32 _oneof_case_[1];
+
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ThresholdInformation final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ThresholdInformation) */ {
+ public:
+  ThresholdInformation();
+  virtual ~ThresholdInformation();
+
+  ThresholdInformation(const ThresholdInformation& from);
+
+  inline ThresholdInformation& operator=(const ThresholdInformation& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ThresholdInformation(ThresholdInformation&& from) noexcept
+    : ThresholdInformation() {
+    *this = ::std::move(from);
+  }
+
+  inline ThresholdInformation& operator=(ThresholdInformation&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ThresholdInformation& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ThresholdInformation* internal_default_instance() {
+    return reinterpret_cast<const ThresholdInformation*>(
+               &_ThresholdInformation_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    3;
+
+  void Swap(ThresholdInformation* other);
+  friend void swap(ThresholdInformation& a, ThresholdInformation& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ThresholdInformation* New() const final {
+    return CreateMaybeMessage<ThresholdInformation>(nullptr);
+  }
+
+  ThresholdInformation* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ThresholdInformation>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ThresholdInformation& from);
+  void MergeFrom(const ThresholdInformation& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ThresholdInformation* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.ValueType observed_value = 1;
+  bool has_observed_value() const;
+  void clear_observed_value();
+  static const int kObservedValueFieldNumber = 1;
+  const ::dmi::ValueType& observed_value() const;
+  ::dmi::ValueType* release_observed_value();
+  ::dmi::ValueType* mutable_observed_value();
+  void set_allocated_observed_value(::dmi::ValueType* observed_value);
+
+  // .dmi.Thresholds thresholds = 2;
+  bool has_thresholds() const;
+  void clear_thresholds();
+  static const int kThresholdsFieldNumber = 2;
+  const ::dmi::Thresholds& thresholds() const;
+  ::dmi::Thresholds* release_thresholds();
+  ::dmi::Thresholds* mutable_thresholds();
+  void set_allocated_thresholds(::dmi::Thresholds* thresholds);
+
+  // @@protoc_insertion_point(class_scope:dmi.ThresholdInformation)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::ValueType* observed_value_;
+  ::dmi::Thresholds* thresholds_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class EventCfg final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventCfg) */ {
+ public:
+  EventCfg();
+  virtual ~EventCfg();
+
+  EventCfg(const EventCfg& from);
+
+  inline EventCfg& operator=(const EventCfg& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  EventCfg(EventCfg&& from) noexcept
+    : EventCfg() {
+    *this = ::std::move(from);
+  }
+
+  inline EventCfg& operator=(EventCfg&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const EventCfg& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const EventCfg* internal_default_instance() {
+    return reinterpret_cast<const EventCfg*>(
+               &_EventCfg_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    4;
+
+  void Swap(EventCfg* other);
+  friend void swap(EventCfg& a, EventCfg& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline EventCfg* New() const final {
+    return CreateMaybeMessage<EventCfg>(nullptr);
+  }
+
+  EventCfg* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<EventCfg>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const EventCfg& from);
+  void MergeFrom(const EventCfg& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(EventCfg* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.Thresholds thresholds = 3;
+  bool has_thresholds() const;
+  void clear_thresholds();
+  static const int kThresholdsFieldNumber = 3;
+  const ::dmi::Thresholds& thresholds() const;
+  ::dmi::Thresholds* release_thresholds();
+  ::dmi::Thresholds* mutable_thresholds();
+  void set_allocated_thresholds(::dmi::Thresholds* thresholds);
+
+  // .dmi.EventIds event_id = 1;
+  void clear_event_id();
+  static const int kEventIdFieldNumber = 1;
+  ::dmi::EventIds event_id() const;
+  void set_event_id(::dmi::EventIds value);
+
+  // bool is_configured = 2;
+  void clear_is_configured();
+  static const int kIsConfiguredFieldNumber = 2;
+  bool is_configured() const;
+  void set_is_configured(bool value);
+
+  // @@protoc_insertion_point(class_scope:dmi.EventCfg)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::Thresholds* thresholds_;
+  int event_id_;
+  bool is_configured_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class EventsCfg final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventsCfg) */ {
+ public:
+  EventsCfg();
+  virtual ~EventsCfg();
+
+  EventsCfg(const EventsCfg& from);
+
+  inline EventsCfg& operator=(const EventsCfg& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  EventsCfg(EventsCfg&& from) noexcept
+    : EventsCfg() {
+    *this = ::std::move(from);
+  }
+
+  inline EventsCfg& operator=(EventsCfg&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const EventsCfg& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const EventsCfg* internal_default_instance() {
+    return reinterpret_cast<const EventsCfg*>(
+               &_EventsCfg_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    5;
+
+  void Swap(EventsCfg* other);
+  friend void swap(EventsCfg& a, EventsCfg& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline EventsCfg* New() const final {
+    return CreateMaybeMessage<EventsCfg>(nullptr);
+  }
+
+  EventsCfg* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<EventsCfg>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const EventsCfg& from);
+  void MergeFrom(const EventsCfg& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(EventsCfg* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated .dmi.EventCfg items = 1;
+  int items_size() const;
+  void clear_items();
+  static const int kItemsFieldNumber = 1;
+  ::dmi::EventCfg* mutable_items(int index);
+  ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg >*
+      mutable_items();
+  const ::dmi::EventCfg& items(int index) const;
+  ::dmi::EventCfg* add_items();
+  const ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg >&
+      items() const;
+
+  // @@protoc_insertion_point(class_scope:dmi.EventsCfg)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg > items_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ListEventsResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ListEventsResponse) */ {
+ public:
+  ListEventsResponse();
+  virtual ~ListEventsResponse();
+
+  ListEventsResponse(const ListEventsResponse& from);
+
+  inline ListEventsResponse& operator=(const ListEventsResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ListEventsResponse(ListEventsResponse&& from) noexcept
+    : ListEventsResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline ListEventsResponse& operator=(ListEventsResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const ListEventsResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const ListEventsResponse* internal_default_instance() {
+    return reinterpret_cast<const ListEventsResponse*>(
+               &_ListEventsResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    6;
+
+  void Swap(ListEventsResponse* other);
+  friend void swap(ListEventsResponse& a, ListEventsResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ListEventsResponse* New() const final {
+    return CreateMaybeMessage<ListEventsResponse>(nullptr);
+  }
+
+  ListEventsResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<ListEventsResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const ListEventsResponse& from);
+  void MergeFrom(const ListEventsResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ListEventsResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef ListEventsResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    ListEventsResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    ListEventsResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    ListEventsResponse_Reason_INTERNAL_ERROR;
+  static const Reason DEVICE_UNREACHABLE =
+    ListEventsResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return ListEventsResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    ListEventsResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    ListEventsResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    ListEventsResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return ListEventsResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return ListEventsResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return ListEventsResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 4;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 4;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.EventsCfg events = 3;
+  bool has_events() const;
+  void clear_events();
+  static const int kEventsFieldNumber = 3;
+  const ::dmi::EventsCfg& events() const;
+  ::dmi::EventsCfg* release_events();
+  ::dmi::EventsCfg* mutable_events();
+  void set_allocated_events(::dmi::EventsCfg* events);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.ListEventsResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::ListEventsResponse_Reason reason() const;
+  void set_reason(::dmi::ListEventsResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.ListEventsResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  ::dmi::EventsCfg* events_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class EventsConfigurationRequest final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventsConfigurationRequest) */ {
+ public:
+  EventsConfigurationRequest();
+  virtual ~EventsConfigurationRequest();
+
+  EventsConfigurationRequest(const EventsConfigurationRequest& from);
+
+  inline EventsConfigurationRequest& operator=(const EventsConfigurationRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  EventsConfigurationRequest(EventsConfigurationRequest&& from) noexcept
+    : EventsConfigurationRequest() {
+    *this = ::std::move(from);
+  }
+
+  inline EventsConfigurationRequest& operator=(EventsConfigurationRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const EventsConfigurationRequest& default_instance();
+
+  enum OperationCase {
+    kChanges = 2,
+    kResetToDefault = 3,
+    OPERATION_NOT_SET = 0,
+  };
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const EventsConfigurationRequest* internal_default_instance() {
+    return reinterpret_cast<const EventsConfigurationRequest*>(
+               &_EventsConfigurationRequest_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    7;
+
+  void Swap(EventsConfigurationRequest* other);
+  friend void swap(EventsConfigurationRequest& a, EventsConfigurationRequest& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline EventsConfigurationRequest* New() const final {
+    return CreateMaybeMessage<EventsConfigurationRequest>(nullptr);
+  }
+
+  EventsConfigurationRequest* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<EventsConfigurationRequest>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const EventsConfigurationRequest& from);
+  void MergeFrom(const EventsConfigurationRequest& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(EventsConfigurationRequest* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // .dmi.EventsCfg changes = 2;
+  bool has_changes() const;
+  void clear_changes();
+  static const int kChangesFieldNumber = 2;
+  const ::dmi::EventsCfg& changes() const;
+  ::dmi::EventsCfg* release_changes();
+  ::dmi::EventsCfg* mutable_changes();
+  void set_allocated_changes(::dmi::EventsCfg* changes);
+
+  // bool reset_to_default = 3;
+  private:
+  bool has_reset_to_default() const;
+  public:
+  void clear_reset_to_default();
+  static const int kResetToDefaultFieldNumber = 3;
+  bool reset_to_default() const;
+  void set_reset_to_default(bool value);
+
+  void clear_operation();
+  OperationCase operation_case() const;
+  // @@protoc_insertion_point(class_scope:dmi.EventsConfigurationRequest)
+ private:
+  class HasBitSetters;
+  void set_has_changes();
+  void set_has_reset_to_default();
+
+  inline bool has_operation() const;
+  inline void clear_has_operation();
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::dmi::Uuid* device_uuid_;
+  union OperationUnion {
+    OperationUnion() {}
+    ::dmi::EventsCfg* changes_;
+    bool reset_to_default_;
+  } operation_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  ::google::protobuf::uint32 _oneof_case_[1];
+
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class EventsConfigurationResponse final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventsConfigurationResponse) */ {
+ public:
+  EventsConfigurationResponse();
+  virtual ~EventsConfigurationResponse();
+
+  EventsConfigurationResponse(const EventsConfigurationResponse& from);
+
+  inline EventsConfigurationResponse& operator=(const EventsConfigurationResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  EventsConfigurationResponse(EventsConfigurationResponse&& from) noexcept
+    : EventsConfigurationResponse() {
+    *this = ::std::move(from);
+  }
+
+  inline EventsConfigurationResponse& operator=(EventsConfigurationResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const EventsConfigurationResponse& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const EventsConfigurationResponse* internal_default_instance() {
+    return reinterpret_cast<const EventsConfigurationResponse*>(
+               &_EventsConfigurationResponse_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    8;
+
+  void Swap(EventsConfigurationResponse* other);
+  friend void swap(EventsConfigurationResponse& a, EventsConfigurationResponse& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline EventsConfigurationResponse* New() const final {
+    return CreateMaybeMessage<EventsConfigurationResponse>(nullptr);
+  }
+
+  EventsConfigurationResponse* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<EventsConfigurationResponse>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const EventsConfigurationResponse& from);
+  void MergeFrom(const EventsConfigurationResponse& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(EventsConfigurationResponse* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  typedef EventsConfigurationResponse_Reason Reason;
+  static const Reason UNDEFINED_REASON =
+    EventsConfigurationResponse_Reason_UNDEFINED_REASON;
+  static const Reason UNKNOWN_DEVICE =
+    EventsConfigurationResponse_Reason_UNKNOWN_DEVICE;
+  static const Reason INTERNAL_ERROR =
+    EventsConfigurationResponse_Reason_INTERNAL_ERROR;
+  static const Reason INVALID_CONFIG =
+    EventsConfigurationResponse_Reason_INVALID_CONFIG;
+  static const Reason DEVICE_UNREACHABLE =
+    EventsConfigurationResponse_Reason_DEVICE_UNREACHABLE;
+  static inline bool Reason_IsValid(int value) {
+    return EventsConfigurationResponse_Reason_IsValid(value);
+  }
+  static const Reason Reason_MIN =
+    EventsConfigurationResponse_Reason_Reason_MIN;
+  static const Reason Reason_MAX =
+    EventsConfigurationResponse_Reason_Reason_MAX;
+  static const int Reason_ARRAYSIZE =
+    EventsConfigurationResponse_Reason_Reason_ARRAYSIZE;
+  static inline const ::google::protobuf::EnumDescriptor*
+  Reason_descriptor() {
+    return EventsConfigurationResponse_Reason_descriptor();
+  }
+  static inline const ::std::string& Reason_Name(Reason value) {
+    return EventsConfigurationResponse_Reason_Name(value);
+  }
+  static inline bool Reason_Parse(const ::std::string& name,
+      Reason* value) {
+    return EventsConfigurationResponse_Reason_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // string reason_detail = 3;
+  void clear_reason_detail();
+  static const int kReasonDetailFieldNumber = 3;
+  const ::std::string& reason_detail() const;
+  void set_reason_detail(const ::std::string& value);
+  #if LANG_CXX11
+  void set_reason_detail(::std::string&& value);
+  #endif
+  void set_reason_detail(const char* value);
+  void set_reason_detail(const char* value, size_t size);
+  ::std::string* mutable_reason_detail();
+  ::std::string* release_reason_detail();
+  void set_allocated_reason_detail(::std::string* reason_detail);
+
+  // .dmi.Status status = 1;
+  void clear_status();
+  static const int kStatusFieldNumber = 1;
+  ::dmi::Status status() const;
+  void set_status(::dmi::Status value);
+
+  // .dmi.EventsConfigurationResponse.Reason reason = 2;
+  void clear_reason();
+  static const int kReasonFieldNumber = 2;
+  ::dmi::EventsConfigurationResponse_Reason reason() const;
+  void set_reason(::dmi::EventsConfigurationResponse_Reason value);
+
+  // @@protoc_insertion_point(class_scope:dmi.EventsConfigurationResponse)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
+  int status_;
+  int reason_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class EventMetaData final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventMetaData) */ {
+ public:
+  EventMetaData();
+  virtual ~EventMetaData();
+
+  EventMetaData(const EventMetaData& from);
+
+  inline EventMetaData& operator=(const EventMetaData& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  EventMetaData(EventMetaData&& from) noexcept
+    : EventMetaData() {
+    *this = ::std::move(from);
+  }
+
+  inline EventMetaData& operator=(EventMetaData&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const EventMetaData& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const EventMetaData* internal_default_instance() {
+    return reinterpret_cast<const EventMetaData*>(
+               &_EventMetaData_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    9;
+
+  void Swap(EventMetaData* other);
+  friend void swap(EventMetaData& a, EventMetaData& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline EventMetaData* New() const final {
+    return CreateMaybeMessage<EventMetaData>(nullptr);
+  }
+
+  EventMetaData* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<EventMetaData>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const EventMetaData& from);
+  void MergeFrom(const EventMetaData& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(EventMetaData* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string component_name = 3;
+  void clear_component_name();
+  static const int kComponentNameFieldNumber = 3;
+  const ::std::string& component_name() const;
+  void set_component_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_component_name(::std::string&& value);
+  #endif
+  void set_component_name(const char* value);
+  void set_component_name(const char* value, size_t size);
+  ::std::string* mutable_component_name();
+  ::std::string* release_component_name();
+  void set_allocated_component_name(::std::string* component_name);
+
+  // .dmi.Uuid device_uuid = 1;
+  bool has_device_uuid() const;
+  void clear_device_uuid();
+  static const int kDeviceUuidFieldNumber = 1;
+  const ::dmi::Uuid& device_uuid() const;
+  ::dmi::Uuid* release_device_uuid();
+  ::dmi::Uuid* mutable_device_uuid();
+  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);
+
+  // .dmi.Uuid component_uuid = 2;
+  bool has_component_uuid() const;
+  void clear_component_uuid();
+  static const int kComponentUuidFieldNumber = 2;
+  const ::dmi::Uuid& component_uuid() const;
+  ::dmi::Uuid* release_component_uuid();
+  ::dmi::Uuid* mutable_component_uuid();
+  void set_allocated_component_uuid(::dmi::Uuid* component_uuid);
+
+  // @@protoc_insertion_point(class_scope:dmi.EventMetaData)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr component_name_;
+  ::dmi::Uuid* device_uuid_;
+  ::dmi::Uuid* component_uuid_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// -------------------------------------------------------------------
+
+class Event final :
+    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.Event) */ {
+ public:
+  Event();
+  virtual ~Event();
+
+  Event(const Event& from);
+
+  inline Event& operator=(const Event& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  Event(Event&& from) noexcept
+    : Event() {
+    *this = ::std::move(from);
+  }
+
+  inline Event& operator=(Event&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  static const ::google::protobuf::Descriptor* descriptor() {
+    return default_instance().GetDescriptor();
+  }
+  static const Event& default_instance();
+
+  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
+  static inline const Event* internal_default_instance() {
+    return reinterpret_cast<const Event*>(
+               &_Event_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    10;
+
+  void Swap(Event* other);
+  friend void swap(Event& a, Event& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Event* New() const final {
+    return CreateMaybeMessage<Event>(nullptr);
+  }
+
+  Event* New(::google::protobuf::Arena* arena) const final {
+    return CreateMaybeMessage<Event>(arena);
+  }
+  void CopyFrom(const ::google::protobuf::Message& from) final;
+  void MergeFrom(const ::google::protobuf::Message& from) final;
+  void CopyFrom(const Event& from);
+  void MergeFrom(const Event& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
+  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
+  #else
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) final;
+  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const final;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      ::google::protobuf::uint8* target) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Event* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return nullptr;
+  }
+  inline void* MaybeArenaPtr() const {
+    return nullptr;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const final;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // string add_info = 5;
+  void clear_add_info();
+  static const int kAddInfoFieldNumber = 5;
+  const ::std::string& add_info() const;
+  void set_add_info(const ::std::string& value);
+  #if LANG_CXX11
+  void set_add_info(::std::string&& value);
+  #endif
+  void set_add_info(const char* value);
+  void set_add_info(const char* value, size_t size);
+  ::std::string* mutable_add_info();
+  ::std::string* release_add_info();
+  void set_allocated_add_info(::std::string* add_info);
+
+  // .dmi.EventMetaData event_metadata = 1;
+  bool has_event_metadata() const;
+  void clear_event_metadata();
+  static const int kEventMetadataFieldNumber = 1;
+  const ::dmi::EventMetaData& event_metadata() const;
+  ::dmi::EventMetaData* release_event_metadata();
+  ::dmi::EventMetaData* mutable_event_metadata();
+  void set_allocated_event_metadata(::dmi::EventMetaData* event_metadata);
+
+  // .google.protobuf.Timestamp raised_ts = 3;
+  bool has_raised_ts() const;
+  void clear_raised_ts();
+  static const int kRaisedTsFieldNumber = 3;
+  const ::google::protobuf::Timestamp& raised_ts() const;
+  ::google::protobuf::Timestamp* release_raised_ts();
+  ::google::protobuf::Timestamp* mutable_raised_ts();
+  void set_allocated_raised_ts(::google::protobuf::Timestamp* raised_ts);
+
+  // .dmi.ThresholdInformation threshold_info = 4;
+  bool has_threshold_info() const;
+  void clear_threshold_info();
+  static const int kThresholdInfoFieldNumber = 4;
+  const ::dmi::ThresholdInformation& threshold_info() const;
+  ::dmi::ThresholdInformation* release_threshold_info();
+  ::dmi::ThresholdInformation* mutable_threshold_info();
+  void set_allocated_threshold_info(::dmi::ThresholdInformation* threshold_info);
+
+  // .dmi.EventIds event_id = 2;
+  void clear_event_id();
+  static const int kEventIdFieldNumber = 2;
+  ::dmi::EventIds event_id() const;
+  void set_event_id(::dmi::EventIds value);
+
+  // @@protoc_insertion_point(class_scope:dmi.Event)
+ private:
+  class HasBitSetters;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::ArenaStringPtr add_info_;
+  ::dmi::EventMetaData* event_metadata_;
+  ::google::protobuf::Timestamp* raised_ts_;
+  ::dmi::ThresholdInformation* threshold_info_;
+  int event_id_;
+  mutable ::google::protobuf::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// ValueType
+
+// int64 int_val = 1;
+inline bool ValueType::has_int_val() const {
+  return val_case() == kIntVal;
+}
+inline void ValueType::set_has_int_val() {
+  _oneof_case_[0] = kIntVal;
+}
+inline void ValueType::clear_int_val() {
+  if (has_int_val()) {
+    val_.int_val_ = PROTOBUF_LONGLONG(0);
+    clear_has_val();
+  }
+}
+inline ::google::protobuf::int64 ValueType::int_val() const {
+  // @@protoc_insertion_point(field_get:dmi.ValueType.int_val)
+  if (has_int_val()) {
+    return val_.int_val_;
+  }
+  return PROTOBUF_LONGLONG(0);
+}
+inline void ValueType::set_int_val(::google::protobuf::int64 value) {
+  if (!has_int_val()) {
+    clear_val();
+    set_has_int_val();
+  }
+  val_.int_val_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ValueType.int_val)
+}
+
+// uint64 uint_val = 2;
+inline bool ValueType::has_uint_val() const {
+  return val_case() == kUintVal;
+}
+inline void ValueType::set_has_uint_val() {
+  _oneof_case_[0] = kUintVal;
+}
+inline void ValueType::clear_uint_val() {
+  if (has_uint_val()) {
+    val_.uint_val_ = PROTOBUF_ULONGLONG(0);
+    clear_has_val();
+  }
+}
+inline ::google::protobuf::uint64 ValueType::uint_val() const {
+  // @@protoc_insertion_point(field_get:dmi.ValueType.uint_val)
+  if (has_uint_val()) {
+    return val_.uint_val_;
+  }
+  return PROTOBUF_ULONGLONG(0);
+}
+inline void ValueType::set_uint_val(::google::protobuf::uint64 value) {
+  if (!has_uint_val()) {
+    clear_val();
+    set_has_uint_val();
+  }
+  val_.uint_val_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ValueType.uint_val)
+}
+
+// float float_val = 3;
+inline bool ValueType::has_float_val() const {
+  return val_case() == kFloatVal;
+}
+inline void ValueType::set_has_float_val() {
+  _oneof_case_[0] = kFloatVal;
+}
+inline void ValueType::clear_float_val() {
+  if (has_float_val()) {
+    val_.float_val_ = 0;
+    clear_has_val();
+  }
+}
+inline float ValueType::float_val() const {
+  // @@protoc_insertion_point(field_get:dmi.ValueType.float_val)
+  if (has_float_val()) {
+    return val_.float_val_;
+  }
+  return 0;
+}
+inline void ValueType::set_float_val(float value) {
+  if (!has_float_val()) {
+    clear_val();
+    set_has_float_val();
+  }
+  val_.float_val_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ValueType.float_val)
+}
+
+inline bool ValueType::has_val() const {
+  return val_case() != VAL_NOT_SET;
+}
+inline void ValueType::clear_has_val() {
+  _oneof_case_[0] = VAL_NOT_SET;
+}
+inline ValueType::ValCase ValueType::val_case() const {
+  return ValueType::ValCase(_oneof_case_[0]);
+}
+// -------------------------------------------------------------------
+
+// WaterMarks
+
+// .dmi.ValueType high = 1;
+inline bool WaterMarks::has_high() const {
+  return this != internal_default_instance() && high_ != nullptr;
+}
+inline void WaterMarks::clear_high() {
+  if (GetArenaNoVirtual() == nullptr && high_ != nullptr) {
+    delete high_;
+  }
+  high_ = nullptr;
+}
+inline const ::dmi::ValueType& WaterMarks::high() const {
+  const ::dmi::ValueType* p = high_;
+  // @@protoc_insertion_point(field_get:dmi.WaterMarks.high)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ValueType*>(
+      &::dmi::_ValueType_default_instance_);
+}
+inline ::dmi::ValueType* WaterMarks::release_high() {
+  // @@protoc_insertion_point(field_release:dmi.WaterMarks.high)
+  
+  ::dmi::ValueType* temp = high_;
+  high_ = nullptr;
+  return temp;
+}
+inline ::dmi::ValueType* WaterMarks::mutable_high() {
+  
+  if (high_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ValueType>(GetArenaNoVirtual());
+    high_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.WaterMarks.high)
+  return high_;
+}
+inline void WaterMarks::set_allocated_high(::dmi::ValueType* high) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete high_;
+  }
+  if (high) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      high = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, high, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  high_ = high;
+  // @@protoc_insertion_point(field_set_allocated:dmi.WaterMarks.high)
+}
+
+// .dmi.ValueType low = 2;
+inline bool WaterMarks::has_low() const {
+  return this != internal_default_instance() && low_ != nullptr;
+}
+inline void WaterMarks::clear_low() {
+  if (GetArenaNoVirtual() == nullptr && low_ != nullptr) {
+    delete low_;
+  }
+  low_ = nullptr;
+}
+inline const ::dmi::ValueType& WaterMarks::low() const {
+  const ::dmi::ValueType* p = low_;
+  // @@protoc_insertion_point(field_get:dmi.WaterMarks.low)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ValueType*>(
+      &::dmi::_ValueType_default_instance_);
+}
+inline ::dmi::ValueType* WaterMarks::release_low() {
+  // @@protoc_insertion_point(field_release:dmi.WaterMarks.low)
+  
+  ::dmi::ValueType* temp = low_;
+  low_ = nullptr;
+  return temp;
+}
+inline ::dmi::ValueType* WaterMarks::mutable_low() {
+  
+  if (low_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ValueType>(GetArenaNoVirtual());
+    low_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.WaterMarks.low)
+  return low_;
+}
+inline void WaterMarks::set_allocated_low(::dmi::ValueType* low) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete low_;
+  }
+  if (low) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      low = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, low, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  low_ = low;
+  // @@protoc_insertion_point(field_set_allocated:dmi.WaterMarks.low)
+}
+
+// -------------------------------------------------------------------
+
+// Thresholds
+
+// .dmi.WaterMarks upper = 1;
+inline bool Thresholds::has_upper() const {
+  return threshold_case() == kUpper;
+}
+inline void Thresholds::set_has_upper() {
+  _oneof_case_[0] = kUpper;
+}
+inline void Thresholds::clear_upper() {
+  if (has_upper()) {
+    delete threshold_.upper_;
+    clear_has_threshold();
+  }
+}
+inline ::dmi::WaterMarks* Thresholds::release_upper() {
+  // @@protoc_insertion_point(field_release:dmi.Thresholds.upper)
+  if (has_upper()) {
+    clear_has_threshold();
+      ::dmi::WaterMarks* temp = threshold_.upper_;
+    threshold_.upper_ = nullptr;
+    return temp;
+  } else {
+    return nullptr;
+  }
+}
+inline const ::dmi::WaterMarks& Thresholds::upper() const {
+  // @@protoc_insertion_point(field_get:dmi.Thresholds.upper)
+  return has_upper()
+      ? *threshold_.upper_
+      : *reinterpret_cast< ::dmi::WaterMarks*>(&::dmi::_WaterMarks_default_instance_);
+}
+inline ::dmi::WaterMarks* Thresholds::mutable_upper() {
+  if (!has_upper()) {
+    clear_threshold();
+    set_has_upper();
+    threshold_.upper_ = CreateMaybeMessage< ::dmi::WaterMarks >(
+        GetArenaNoVirtual());
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Thresholds.upper)
+  return threshold_.upper_;
+}
+
+// .dmi.WaterMarks lower = 2;
+inline bool Thresholds::has_lower() const {
+  return threshold_case() == kLower;
+}
+inline void Thresholds::set_has_lower() {
+  _oneof_case_[0] = kLower;
+}
+inline void Thresholds::clear_lower() {
+  if (has_lower()) {
+    delete threshold_.lower_;
+    clear_has_threshold();
+  }
+}
+inline ::dmi::WaterMarks* Thresholds::release_lower() {
+  // @@protoc_insertion_point(field_release:dmi.Thresholds.lower)
+  if (has_lower()) {
+    clear_has_threshold();
+      ::dmi::WaterMarks* temp = threshold_.lower_;
+    threshold_.lower_ = nullptr;
+    return temp;
+  } else {
+    return nullptr;
+  }
+}
+inline const ::dmi::WaterMarks& Thresholds::lower() const {
+  // @@protoc_insertion_point(field_get:dmi.Thresholds.lower)
+  return has_lower()
+      ? *threshold_.lower_
+      : *reinterpret_cast< ::dmi::WaterMarks*>(&::dmi::_WaterMarks_default_instance_);
+}
+inline ::dmi::WaterMarks* Thresholds::mutable_lower() {
+  if (!has_lower()) {
+    clear_threshold();
+    set_has_lower();
+    threshold_.lower_ = CreateMaybeMessage< ::dmi::WaterMarks >(
+        GetArenaNoVirtual());
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Thresholds.lower)
+  return threshold_.lower_;
+}
+
+inline bool Thresholds::has_threshold() const {
+  return threshold_case() != THRESHOLD_NOT_SET;
+}
+inline void Thresholds::clear_has_threshold() {
+  _oneof_case_[0] = THRESHOLD_NOT_SET;
+}
+inline Thresholds::ThresholdCase Thresholds::threshold_case() const {
+  return Thresholds::ThresholdCase(_oneof_case_[0]);
+}
+// -------------------------------------------------------------------
+
+// ThresholdInformation
+
+// .dmi.ValueType observed_value = 1;
+inline bool ThresholdInformation::has_observed_value() const {
+  return this != internal_default_instance() && observed_value_ != nullptr;
+}
+inline void ThresholdInformation::clear_observed_value() {
+  if (GetArenaNoVirtual() == nullptr && observed_value_ != nullptr) {
+    delete observed_value_;
+  }
+  observed_value_ = nullptr;
+}
+inline const ::dmi::ValueType& ThresholdInformation::observed_value() const {
+  const ::dmi::ValueType* p = observed_value_;
+  // @@protoc_insertion_point(field_get:dmi.ThresholdInformation.observed_value)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ValueType*>(
+      &::dmi::_ValueType_default_instance_);
+}
+inline ::dmi::ValueType* ThresholdInformation::release_observed_value() {
+  // @@protoc_insertion_point(field_release:dmi.ThresholdInformation.observed_value)
+  
+  ::dmi::ValueType* temp = observed_value_;
+  observed_value_ = nullptr;
+  return temp;
+}
+inline ::dmi::ValueType* ThresholdInformation::mutable_observed_value() {
+  
+  if (observed_value_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ValueType>(GetArenaNoVirtual());
+    observed_value_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ThresholdInformation.observed_value)
+  return observed_value_;
+}
+inline void ThresholdInformation::set_allocated_observed_value(::dmi::ValueType* observed_value) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete observed_value_;
+  }
+  if (observed_value) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      observed_value = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, observed_value, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  observed_value_ = observed_value;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ThresholdInformation.observed_value)
+}
+
+// .dmi.Thresholds thresholds = 2;
+inline bool ThresholdInformation::has_thresholds() const {
+  return this != internal_default_instance() && thresholds_ != nullptr;
+}
+inline void ThresholdInformation::clear_thresholds() {
+  if (GetArenaNoVirtual() == nullptr && thresholds_ != nullptr) {
+    delete thresholds_;
+  }
+  thresholds_ = nullptr;
+}
+inline const ::dmi::Thresholds& ThresholdInformation::thresholds() const {
+  const ::dmi::Thresholds* p = thresholds_;
+  // @@protoc_insertion_point(field_get:dmi.ThresholdInformation.thresholds)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Thresholds*>(
+      &::dmi::_Thresholds_default_instance_);
+}
+inline ::dmi::Thresholds* ThresholdInformation::release_thresholds() {
+  // @@protoc_insertion_point(field_release:dmi.ThresholdInformation.thresholds)
+  
+  ::dmi::Thresholds* temp = thresholds_;
+  thresholds_ = nullptr;
+  return temp;
+}
+inline ::dmi::Thresholds* ThresholdInformation::mutable_thresholds() {
+  
+  if (thresholds_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Thresholds>(GetArenaNoVirtual());
+    thresholds_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ThresholdInformation.thresholds)
+  return thresholds_;
+}
+inline void ThresholdInformation::set_allocated_thresholds(::dmi::Thresholds* thresholds) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete thresholds_;
+  }
+  if (thresholds) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      thresholds = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, thresholds, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  thresholds_ = thresholds;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ThresholdInformation.thresholds)
+}
+
+// -------------------------------------------------------------------
+
+// EventCfg
+
+// .dmi.EventIds event_id = 1;
+inline void EventCfg::clear_event_id() {
+  event_id_ = 0;
+}
+inline ::dmi::EventIds EventCfg::event_id() const {
+  // @@protoc_insertion_point(field_get:dmi.EventCfg.event_id)
+  return static_cast< ::dmi::EventIds >(event_id_);
+}
+inline void EventCfg::set_event_id(::dmi::EventIds value) {
+  
+  event_id_ = value;
+  // @@protoc_insertion_point(field_set:dmi.EventCfg.event_id)
+}
+
+// bool is_configured = 2;
+inline void EventCfg::clear_is_configured() {
+  is_configured_ = false;
+}
+inline bool EventCfg::is_configured() const {
+  // @@protoc_insertion_point(field_get:dmi.EventCfg.is_configured)
+  return is_configured_;
+}
+inline void EventCfg::set_is_configured(bool value) {
+  
+  is_configured_ = value;
+  // @@protoc_insertion_point(field_set:dmi.EventCfg.is_configured)
+}
+
+// .dmi.Thresholds thresholds = 3;
+inline bool EventCfg::has_thresholds() const {
+  return this != internal_default_instance() && thresholds_ != nullptr;
+}
+inline void EventCfg::clear_thresholds() {
+  if (GetArenaNoVirtual() == nullptr && thresholds_ != nullptr) {
+    delete thresholds_;
+  }
+  thresholds_ = nullptr;
+}
+inline const ::dmi::Thresholds& EventCfg::thresholds() const {
+  const ::dmi::Thresholds* p = thresholds_;
+  // @@protoc_insertion_point(field_get:dmi.EventCfg.thresholds)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Thresholds*>(
+      &::dmi::_Thresholds_default_instance_);
+}
+inline ::dmi::Thresholds* EventCfg::release_thresholds() {
+  // @@protoc_insertion_point(field_release:dmi.EventCfg.thresholds)
+  
+  ::dmi::Thresholds* temp = thresholds_;
+  thresholds_ = nullptr;
+  return temp;
+}
+inline ::dmi::Thresholds* EventCfg::mutable_thresholds() {
+  
+  if (thresholds_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Thresholds>(GetArenaNoVirtual());
+    thresholds_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.EventCfg.thresholds)
+  return thresholds_;
+}
+inline void EventCfg::set_allocated_thresholds(::dmi::Thresholds* thresholds) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete thresholds_;
+  }
+  if (thresholds) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      thresholds = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, thresholds, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  thresholds_ = thresholds;
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventCfg.thresholds)
+}
+
+// -------------------------------------------------------------------
+
+// EventsCfg
+
+// repeated .dmi.EventCfg items = 1;
+inline int EventsCfg::items_size() const {
+  return items_.size();
+}
+inline void EventsCfg::clear_items() {
+  items_.Clear();
+}
+inline ::dmi::EventCfg* EventsCfg::mutable_items(int index) {
+  // @@protoc_insertion_point(field_mutable:dmi.EventsCfg.items)
+  return items_.Mutable(index);
+}
+inline ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg >*
+EventsCfg::mutable_items() {
+  // @@protoc_insertion_point(field_mutable_list:dmi.EventsCfg.items)
+  return &items_;
+}
+inline const ::dmi::EventCfg& EventsCfg::items(int index) const {
+  // @@protoc_insertion_point(field_get:dmi.EventsCfg.items)
+  return items_.Get(index);
+}
+inline ::dmi::EventCfg* EventsCfg::add_items() {
+  // @@protoc_insertion_point(field_add:dmi.EventsCfg.items)
+  return items_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg >&
+EventsCfg::items() const {
+  // @@protoc_insertion_point(field_list:dmi.EventsCfg.items)
+  return items_;
+}
+
+// -------------------------------------------------------------------
+
+// ListEventsResponse
+
+// .dmi.Status status = 1;
+inline void ListEventsResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status ListEventsResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.ListEventsResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void ListEventsResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ListEventsResponse.status)
+}
+
+// .dmi.ListEventsResponse.Reason reason = 2;
+inline void ListEventsResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::ListEventsResponse_Reason ListEventsResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.ListEventsResponse.reason)
+  return static_cast< ::dmi::ListEventsResponse_Reason >(reason_);
+}
+inline void ListEventsResponse::set_reason(::dmi::ListEventsResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.ListEventsResponse.reason)
+}
+
+// .dmi.EventsCfg events = 3;
+inline bool ListEventsResponse::has_events() const {
+  return this != internal_default_instance() && events_ != nullptr;
+}
+inline void ListEventsResponse::clear_events() {
+  if (GetArenaNoVirtual() == nullptr && events_ != nullptr) {
+    delete events_;
+  }
+  events_ = nullptr;
+}
+inline const ::dmi::EventsCfg& ListEventsResponse::events() const {
+  const ::dmi::EventsCfg* p = events_;
+  // @@protoc_insertion_point(field_get:dmi.ListEventsResponse.events)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::EventsCfg*>(
+      &::dmi::_EventsCfg_default_instance_);
+}
+inline ::dmi::EventsCfg* ListEventsResponse::release_events() {
+  // @@protoc_insertion_point(field_release:dmi.ListEventsResponse.events)
+  
+  ::dmi::EventsCfg* temp = events_;
+  events_ = nullptr;
+  return temp;
+}
+inline ::dmi::EventsCfg* ListEventsResponse::mutable_events() {
+  
+  if (events_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::EventsCfg>(GetArenaNoVirtual());
+    events_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.ListEventsResponse.events)
+  return events_;
+}
+inline void ListEventsResponse::set_allocated_events(::dmi::EventsCfg* events) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete events_;
+  }
+  if (events) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      events = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, events, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  events_ = events;
+  // @@protoc_insertion_point(field_set_allocated:dmi.ListEventsResponse.events)
+}
+
+// string reason_detail = 4;
+inline void ListEventsResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& ListEventsResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.ListEventsResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void ListEventsResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.ListEventsResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void ListEventsResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.ListEventsResponse.reason_detail)
+}
+#endif
+inline void ListEventsResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.ListEventsResponse.reason_detail)
+}
+inline void ListEventsResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.ListEventsResponse.reason_detail)
+}
+inline ::std::string* ListEventsResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.ListEventsResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* ListEventsResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.ListEventsResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void ListEventsResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.ListEventsResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// EventsConfigurationRequest
+
+// .dmi.Uuid device_uuid = 1;
+inline bool EventsConfigurationRequest::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& EventsConfigurationRequest::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationRequest.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* EventsConfigurationRequest::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.EventsConfigurationRequest.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* EventsConfigurationRequest::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.EventsConfigurationRequest.device_uuid)
+  return device_uuid_;
+}
+inline void EventsConfigurationRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventsConfigurationRequest.device_uuid)
+}
+
+// .dmi.EventsCfg changes = 2;
+inline bool EventsConfigurationRequest::has_changes() const {
+  return operation_case() == kChanges;
+}
+inline void EventsConfigurationRequest::set_has_changes() {
+  _oneof_case_[0] = kChanges;
+}
+inline void EventsConfigurationRequest::clear_changes() {
+  if (has_changes()) {
+    delete operation_.changes_;
+    clear_has_operation();
+  }
+}
+inline ::dmi::EventsCfg* EventsConfigurationRequest::release_changes() {
+  // @@protoc_insertion_point(field_release:dmi.EventsConfigurationRequest.changes)
+  if (has_changes()) {
+    clear_has_operation();
+      ::dmi::EventsCfg* temp = operation_.changes_;
+    operation_.changes_ = nullptr;
+    return temp;
+  } else {
+    return nullptr;
+  }
+}
+inline const ::dmi::EventsCfg& EventsConfigurationRequest::changes() const {
+  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationRequest.changes)
+  return has_changes()
+      ? *operation_.changes_
+      : *reinterpret_cast< ::dmi::EventsCfg*>(&::dmi::_EventsCfg_default_instance_);
+}
+inline ::dmi::EventsCfg* EventsConfigurationRequest::mutable_changes() {
+  if (!has_changes()) {
+    clear_operation();
+    set_has_changes();
+    operation_.changes_ = CreateMaybeMessage< ::dmi::EventsCfg >(
+        GetArenaNoVirtual());
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.EventsConfigurationRequest.changes)
+  return operation_.changes_;
+}
+
+// bool reset_to_default = 3;
+inline bool EventsConfigurationRequest::has_reset_to_default() const {
+  return operation_case() == kResetToDefault;
+}
+inline void EventsConfigurationRequest::set_has_reset_to_default() {
+  _oneof_case_[0] = kResetToDefault;
+}
+inline void EventsConfigurationRequest::clear_reset_to_default() {
+  if (has_reset_to_default()) {
+    operation_.reset_to_default_ = false;
+    clear_has_operation();
+  }
+}
+inline bool EventsConfigurationRequest::reset_to_default() const {
+  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationRequest.reset_to_default)
+  if (has_reset_to_default()) {
+    return operation_.reset_to_default_;
+  }
+  return false;
+}
+inline void EventsConfigurationRequest::set_reset_to_default(bool value) {
+  if (!has_reset_to_default()) {
+    clear_operation();
+    set_has_reset_to_default();
+  }
+  operation_.reset_to_default_ = value;
+  // @@protoc_insertion_point(field_set:dmi.EventsConfigurationRequest.reset_to_default)
+}
+
+inline bool EventsConfigurationRequest::has_operation() const {
+  return operation_case() != OPERATION_NOT_SET;
+}
+inline void EventsConfigurationRequest::clear_has_operation() {
+  _oneof_case_[0] = OPERATION_NOT_SET;
+}
+inline EventsConfigurationRequest::OperationCase EventsConfigurationRequest::operation_case() const {
+  return EventsConfigurationRequest::OperationCase(_oneof_case_[0]);
+}
+// -------------------------------------------------------------------
+
+// EventsConfigurationResponse
+
+// .dmi.Status status = 1;
+inline void EventsConfigurationResponse::clear_status() {
+  status_ = 0;
+}
+inline ::dmi::Status EventsConfigurationResponse::status() const {
+  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationResponse.status)
+  return static_cast< ::dmi::Status >(status_);
+}
+inline void EventsConfigurationResponse::set_status(::dmi::Status value) {
+  
+  status_ = value;
+  // @@protoc_insertion_point(field_set:dmi.EventsConfigurationResponse.status)
+}
+
+// .dmi.EventsConfigurationResponse.Reason reason = 2;
+inline void EventsConfigurationResponse::clear_reason() {
+  reason_ = 0;
+}
+inline ::dmi::EventsConfigurationResponse_Reason EventsConfigurationResponse::reason() const {
+  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationResponse.reason)
+  return static_cast< ::dmi::EventsConfigurationResponse_Reason >(reason_);
+}
+inline void EventsConfigurationResponse::set_reason(::dmi::EventsConfigurationResponse_Reason value) {
+  
+  reason_ = value;
+  // @@protoc_insertion_point(field_set:dmi.EventsConfigurationResponse.reason)
+}
+
+// string reason_detail = 3;
+inline void EventsConfigurationResponse::clear_reason_detail() {
+  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& EventsConfigurationResponse::reason_detail() const {
+  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationResponse.reason_detail)
+  return reason_detail_.GetNoArena();
+}
+inline void EventsConfigurationResponse::set_reason_detail(const ::std::string& value) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.EventsConfigurationResponse.reason_detail)
+}
+#if LANG_CXX11
+inline void EventsConfigurationResponse::set_reason_detail(::std::string&& value) {
+  
+  reason_detail_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.EventsConfigurationResponse.reason_detail)
+}
+#endif
+inline void EventsConfigurationResponse::set_reason_detail(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.EventsConfigurationResponse.reason_detail)
+}
+inline void EventsConfigurationResponse::set_reason_detail(const char* value, size_t size) {
+  
+  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.EventsConfigurationResponse.reason_detail)
+}
+inline ::std::string* EventsConfigurationResponse::mutable_reason_detail() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.EventsConfigurationResponse.reason_detail)
+  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* EventsConfigurationResponse::release_reason_detail() {
+  // @@protoc_insertion_point(field_release:dmi.EventsConfigurationResponse.reason_detail)
+  
+  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void EventsConfigurationResponse::set_allocated_reason_detail(::std::string* reason_detail) {
+  if (reason_detail != nullptr) {
+    
+  } else {
+    
+  }
+  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventsConfigurationResponse.reason_detail)
+}
+
+// -------------------------------------------------------------------
+
+// EventMetaData
+
+// .dmi.Uuid device_uuid = 1;
+inline bool EventMetaData::has_device_uuid() const {
+  return this != internal_default_instance() && device_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& EventMetaData::device_uuid() const {
+  const ::dmi::Uuid* p = device_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.EventMetaData.device_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* EventMetaData::release_device_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.EventMetaData.device_uuid)
+  
+  ::dmi::Uuid* temp = device_uuid_;
+  device_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* EventMetaData::mutable_device_uuid() {
+  
+  if (device_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    device_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.EventMetaData.device_uuid)
+  return device_uuid_;
+}
+inline void EventMetaData::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
+  }
+  if (device_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, device_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  device_uuid_ = device_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventMetaData.device_uuid)
+}
+
+// .dmi.Uuid component_uuid = 2;
+inline bool EventMetaData::has_component_uuid() const {
+  return this != internal_default_instance() && component_uuid_ != nullptr;
+}
+inline const ::dmi::Uuid& EventMetaData::component_uuid() const {
+  const ::dmi::Uuid* p = component_uuid_;
+  // @@protoc_insertion_point(field_get:dmi.EventMetaData.component_uuid)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
+      &::dmi::_Uuid_default_instance_);
+}
+inline ::dmi::Uuid* EventMetaData::release_component_uuid() {
+  // @@protoc_insertion_point(field_release:dmi.EventMetaData.component_uuid)
+  
+  ::dmi::Uuid* temp = component_uuid_;
+  component_uuid_ = nullptr;
+  return temp;
+}
+inline ::dmi::Uuid* EventMetaData::mutable_component_uuid() {
+  
+  if (component_uuid_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
+    component_uuid_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.EventMetaData.component_uuid)
+  return component_uuid_;
+}
+inline void EventMetaData::set_allocated_component_uuid(::dmi::Uuid* component_uuid) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(component_uuid_);
+  }
+  if (component_uuid) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      component_uuid = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, component_uuid, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  component_uuid_ = component_uuid;
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventMetaData.component_uuid)
+}
+
+// string component_name = 3;
+inline void EventMetaData::clear_component_name() {
+  component_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& EventMetaData::component_name() const {
+  // @@protoc_insertion_point(field_get:dmi.EventMetaData.component_name)
+  return component_name_.GetNoArena();
+}
+inline void EventMetaData::set_component_name(const ::std::string& value) {
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.EventMetaData.component_name)
+}
+#if LANG_CXX11
+inline void EventMetaData::set_component_name(::std::string&& value) {
+  
+  component_name_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.EventMetaData.component_name)
+}
+#endif
+inline void EventMetaData::set_component_name(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.EventMetaData.component_name)
+}
+inline void EventMetaData::set_component_name(const char* value, size_t size) {
+  
+  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.EventMetaData.component_name)
+}
+inline ::std::string* EventMetaData::mutable_component_name() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.EventMetaData.component_name)
+  return component_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* EventMetaData::release_component_name() {
+  // @@protoc_insertion_point(field_release:dmi.EventMetaData.component_name)
+  
+  return component_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void EventMetaData::set_allocated_component_name(::std::string* component_name) {
+  if (component_name != nullptr) {
+    
+  } else {
+    
+  }
+  component_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), component_name);
+  // @@protoc_insertion_point(field_set_allocated:dmi.EventMetaData.component_name)
+}
+
+// -------------------------------------------------------------------
+
+// Event
+
+// .dmi.EventMetaData event_metadata = 1;
+inline bool Event::has_event_metadata() const {
+  return this != internal_default_instance() && event_metadata_ != nullptr;
+}
+inline void Event::clear_event_metadata() {
+  if (GetArenaNoVirtual() == nullptr && event_metadata_ != nullptr) {
+    delete event_metadata_;
+  }
+  event_metadata_ = nullptr;
+}
+inline const ::dmi::EventMetaData& Event::event_metadata() const {
+  const ::dmi::EventMetaData* p = event_metadata_;
+  // @@protoc_insertion_point(field_get:dmi.Event.event_metadata)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::EventMetaData*>(
+      &::dmi::_EventMetaData_default_instance_);
+}
+inline ::dmi::EventMetaData* Event::release_event_metadata() {
+  // @@protoc_insertion_point(field_release:dmi.Event.event_metadata)
+  
+  ::dmi::EventMetaData* temp = event_metadata_;
+  event_metadata_ = nullptr;
+  return temp;
+}
+inline ::dmi::EventMetaData* Event::mutable_event_metadata() {
+  
+  if (event_metadata_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::EventMetaData>(GetArenaNoVirtual());
+    event_metadata_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Event.event_metadata)
+  return event_metadata_;
+}
+inline void Event::set_allocated_event_metadata(::dmi::EventMetaData* event_metadata) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete event_metadata_;
+  }
+  if (event_metadata) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      event_metadata = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, event_metadata, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  event_metadata_ = event_metadata;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Event.event_metadata)
+}
+
+// .dmi.EventIds event_id = 2;
+inline void Event::clear_event_id() {
+  event_id_ = 0;
+}
+inline ::dmi::EventIds Event::event_id() const {
+  // @@protoc_insertion_point(field_get:dmi.Event.event_id)
+  return static_cast< ::dmi::EventIds >(event_id_);
+}
+inline void Event::set_event_id(::dmi::EventIds value) {
+  
+  event_id_ = value;
+  // @@protoc_insertion_point(field_set:dmi.Event.event_id)
+}
+
+// .google.protobuf.Timestamp raised_ts = 3;
+inline bool Event::has_raised_ts() const {
+  return this != internal_default_instance() && raised_ts_ != nullptr;
+}
+inline const ::google::protobuf::Timestamp& Event::raised_ts() const {
+  const ::google::protobuf::Timestamp* p = raised_ts_;
+  // @@protoc_insertion_point(field_get:dmi.Event.raised_ts)
+  return p != nullptr ? *p : *reinterpret_cast<const ::google::protobuf::Timestamp*>(
+      &::google::protobuf::_Timestamp_default_instance_);
+}
+inline ::google::protobuf::Timestamp* Event::release_raised_ts() {
+  // @@protoc_insertion_point(field_release:dmi.Event.raised_ts)
+  
+  ::google::protobuf::Timestamp* temp = raised_ts_;
+  raised_ts_ = nullptr;
+  return temp;
+}
+inline ::google::protobuf::Timestamp* Event::mutable_raised_ts() {
+  
+  if (raised_ts_ == nullptr) {
+    auto* p = CreateMaybeMessage<::google::protobuf::Timestamp>(GetArenaNoVirtual());
+    raised_ts_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Event.raised_ts)
+  return raised_ts_;
+}
+inline void Event::set_allocated_raised_ts(::google::protobuf::Timestamp* raised_ts) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete reinterpret_cast< ::google::protobuf::MessageLite*>(raised_ts_);
+  }
+  if (raised_ts) {
+    ::google::protobuf::Arena* submessage_arena =
+      reinterpret_cast<::google::protobuf::MessageLite*>(raised_ts)->GetArena();
+    if (message_arena != submessage_arena) {
+      raised_ts = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, raised_ts, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  raised_ts_ = raised_ts;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Event.raised_ts)
+}
+
+// .dmi.ThresholdInformation threshold_info = 4;
+inline bool Event::has_threshold_info() const {
+  return this != internal_default_instance() && threshold_info_ != nullptr;
+}
+inline void Event::clear_threshold_info() {
+  if (GetArenaNoVirtual() == nullptr && threshold_info_ != nullptr) {
+    delete threshold_info_;
+  }
+  threshold_info_ = nullptr;
+}
+inline const ::dmi::ThresholdInformation& Event::threshold_info() const {
+  const ::dmi::ThresholdInformation* p = threshold_info_;
+  // @@protoc_insertion_point(field_get:dmi.Event.threshold_info)
+  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ThresholdInformation*>(
+      &::dmi::_ThresholdInformation_default_instance_);
+}
+inline ::dmi::ThresholdInformation* Event::release_threshold_info() {
+  // @@protoc_insertion_point(field_release:dmi.Event.threshold_info)
+  
+  ::dmi::ThresholdInformation* temp = threshold_info_;
+  threshold_info_ = nullptr;
+  return temp;
+}
+inline ::dmi::ThresholdInformation* Event::mutable_threshold_info() {
+  
+  if (threshold_info_ == nullptr) {
+    auto* p = CreateMaybeMessage<::dmi::ThresholdInformation>(GetArenaNoVirtual());
+    threshold_info_ = p;
+  }
+  // @@protoc_insertion_point(field_mutable:dmi.Event.threshold_info)
+  return threshold_info_;
+}
+inline void Event::set_allocated_threshold_info(::dmi::ThresholdInformation* threshold_info) {
+  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
+  if (message_arena == nullptr) {
+    delete threshold_info_;
+  }
+  if (threshold_info) {
+    ::google::protobuf::Arena* submessage_arena = nullptr;
+    if (message_arena != submessage_arena) {
+      threshold_info = ::google::protobuf::internal::GetOwnedMessage(
+          message_arena, threshold_info, submessage_arena);
+    }
+    
+  } else {
+    
+  }
+  threshold_info_ = threshold_info;
+  // @@protoc_insertion_point(field_set_allocated:dmi.Event.threshold_info)
+}
+
+// string add_info = 5;
+inline void Event::clear_add_info() {
+  add_info_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline const ::std::string& Event::add_info() const {
+  // @@protoc_insertion_point(field_get:dmi.Event.add_info)
+  return add_info_.GetNoArena();
+}
+inline void Event::set_add_info(const ::std::string& value) {
+  
+  add_info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:dmi.Event.add_info)
+}
+#if LANG_CXX11
+inline void Event::set_add_info(::std::string&& value) {
+  
+  add_info_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:dmi.Event.add_info)
+}
+#endif
+inline void Event::set_add_info(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  
+  add_info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:dmi.Event.add_info)
+}
+inline void Event::set_add_info(const char* value, size_t size) {
+  
+  add_info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:dmi.Event.add_info)
+}
+inline ::std::string* Event::mutable_add_info() {
+  
+  // @@protoc_insertion_point(field_mutable:dmi.Event.add_info)
+  return add_info_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* Event::release_add_info() {
+  // @@protoc_insertion_point(field_release:dmi.Event.add_info)
+  
+  return add_info_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void Event::set_allocated_add_info(::std::string* add_info) {
+  if (add_info != nullptr) {
+    
+  } else {
+    
+  }
+  add_info_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), add_info);
+  // @@protoc_insertion_point(field_set_allocated:dmi.Event.add_info)
+}
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace dmi
+
+namespace google {
+namespace protobuf {
+
+template <> struct is_proto_enum< ::dmi::ListEventsResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ListEventsResponse_Reason>() {
+  return ::dmi::ListEventsResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::EventsConfigurationResponse_Reason> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::EventsConfigurationResponse_Reason>() {
+  return ::dmi::EventsConfigurationResponse_Reason_descriptor();
+}
+template <> struct is_proto_enum< ::dmi::EventIds> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::dmi::EventIds>() {
+  return ::dmi::EventIds_descriptor();
+}
+
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)
+
+#include <google/protobuf/port_undef.inc>
+#endif  // PROTOBUF_INCLUDED_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto
