// 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>
#include <google/protobuf/empty.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
