VOL-4032: gRPC Streams for Events, Metrics

Change-Id: Iff813c7e701490833b8585a6c5516348000e541f
diff --git a/cpp/dmi/hw_events_mgmt_service.grpc.pb.cc b/cpp/dmi/hw_events_mgmt_service.grpc.pb.cc
index 450a295..7168f79 100644
--- a/cpp/dmi/hw_events_mgmt_service.grpc.pb.cc
+++ b/cpp/dmi/hw_events_mgmt_service.grpc.pb.cc
@@ -24,6 +24,7 @@
 static const char* NativeEventsManagementService_method_names[] = {
   "/dmi.NativeEventsManagementService/ListEvents",
   "/dmi.NativeEventsManagementService/UpdateEventsConfiguration",
+  "/dmi.NativeEventsManagementService/StreamEvents",
 };
 
 std::unique_ptr< NativeEventsManagementService::Stub> NativeEventsManagementService::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) {
@@ -35,6 +36,7 @@
 NativeEventsManagementService::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel)
   : channel_(channel), rpcmethod_ListEvents_(NativeEventsManagementService_method_names[0], ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
   , rpcmethod_UpdateEventsConfiguration_(NativeEventsManagementService_method_names[1], ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
+  , rpcmethod_StreamEvents_(NativeEventsManagementService_method_names[2], ::grpc::internal::RpcMethod::SERVER_STREAMING, channel)
   {}
 
 ::grpc::Status NativeEventsManagementService::Stub::ListEvents(::grpc::ClientContext* context, const ::dmi::HardwareID& request, ::dmi::ListEventsResponse* response) {
@@ -93,6 +95,22 @@
   return ::grpc_impl::internal::ClientAsyncResponseReaderFactory< ::dmi::EventsConfigurationResponse>::Create(channel_.get(), cq, rpcmethod_UpdateEventsConfiguration_, context, request, false);
 }
 
+::grpc::ClientReader< ::dmi::Event>* NativeEventsManagementService::Stub::StreamEventsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) {
+  return ::grpc_impl::internal::ClientReaderFactory< ::dmi::Event>::Create(channel_.get(), rpcmethod_StreamEvents_, context, request);
+}
+
+void NativeEventsManagementService::Stub::experimental_async::StreamEvents(::grpc::ClientContext* context, ::google::protobuf::Empty* request, ::grpc::experimental::ClientReadReactor< ::dmi::Event>* reactor) {
+  ::grpc_impl::internal::ClientCallbackReaderFactory< ::dmi::Event>::Create(stub_->channel_.get(), stub_->rpcmethod_StreamEvents_, context, request, reactor);
+}
+
+::grpc::ClientAsyncReader< ::dmi::Event>* NativeEventsManagementService::Stub::AsyncStreamEventsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) {
+  return ::grpc_impl::internal::ClientAsyncReaderFactory< ::dmi::Event>::Create(channel_.get(), cq, rpcmethod_StreamEvents_, context, request, true, tag);
+}
+
+::grpc::ClientAsyncReader< ::dmi::Event>* NativeEventsManagementService::Stub::PrepareAsyncStreamEventsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) {
+  return ::grpc_impl::internal::ClientAsyncReaderFactory< ::dmi::Event>::Create(channel_.get(), cq, rpcmethod_StreamEvents_, context, request, false, nullptr);
+}
+
 NativeEventsManagementService::Service::Service() {
   AddMethod(new ::grpc::internal::RpcServiceMethod(
       NativeEventsManagementService_method_names[0],
@@ -114,6 +132,16 @@
              ::dmi::EventsConfigurationResponse* resp) {
                return service->UpdateEventsConfiguration(ctx, req, resp);
              }, this)));
+  AddMethod(new ::grpc::internal::RpcServiceMethod(
+      NativeEventsManagementService_method_names[2],
+      ::grpc::internal::RpcMethod::SERVER_STREAMING,
+      new ::grpc::internal::ServerStreamingHandler< NativeEventsManagementService::Service, ::google::protobuf::Empty, ::dmi::Event>(
+          [](NativeEventsManagementService::Service* service,
+             ::grpc_impl::ServerContext* ctx,
+             const ::google::protobuf::Empty* req,
+             ::grpc_impl::ServerWriter<::dmi::Event>* writer) {
+               return service->StreamEvents(ctx, req, writer);
+             }, this)));
 }
 
 NativeEventsManagementService::Service::~Service() {
@@ -133,6 +161,13 @@
   return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
 }
 
+::grpc::Status NativeEventsManagementService::Service::StreamEvents(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::grpc::ServerWriter< ::dmi::Event>* writer) {
+  (void) context;
+  (void) request;
+  (void) writer;
+  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+}
+
 
 }  // namespace dmi
 
diff --git a/cpp/dmi/hw_events_mgmt_service.grpc.pb.h b/cpp/dmi/hw_events_mgmt_service.grpc.pb.h
index b6877d1..d247295 100644
--- a/cpp/dmi/hw_events_mgmt_service.grpc.pb.h
+++ b/cpp/dmi/hw_events_mgmt_service.grpc.pb.h
@@ -54,6 +54,16 @@
     std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::dmi::EventsConfigurationResponse>> PrepareAsyncUpdateEventsConfiguration(::grpc::ClientContext* context, const ::dmi::EventsConfigurationRequest& request, ::grpc::CompletionQueue* cq) {
       return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::dmi::EventsConfigurationResponse>>(PrepareAsyncUpdateEventsConfigurationRaw(context, request, cq));
     }
+    // Initiate the server streaming of the events

+    std::unique_ptr< ::grpc::ClientReaderInterface< ::dmi::Event>> StreamEvents(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) {
+      return std::unique_ptr< ::grpc::ClientReaderInterface< ::dmi::Event>>(StreamEventsRaw(context, request));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::dmi::Event>> AsyncStreamEvents(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) {
+      return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::dmi::Event>>(AsyncStreamEventsRaw(context, request, cq, tag));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::dmi::Event>> PrepareAsyncStreamEvents(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::dmi::Event>>(PrepareAsyncStreamEventsRaw(context, request, cq));
+    }
     class experimental_async_interface {
      public:
       virtual ~experimental_async_interface() {}
@@ -85,6 +95,12 @@
       #else
       virtual void UpdateEventsConfiguration(::grpc::ClientContext* context, const ::grpc::ByteBuffer* request, ::dmi::EventsConfigurationResponse* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0;
       #endif
+      // Initiate the server streaming of the events

+      #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      virtual void StreamEvents(::grpc::ClientContext* context, ::google::protobuf::Empty* request, ::grpc::ClientReadReactor< ::dmi::Event>* reactor) = 0;
+      #else
+      virtual void StreamEvents(::grpc::ClientContext* context, ::google::protobuf::Empty* request, ::grpc::experimental::ClientReadReactor< ::dmi::Event>* reactor) = 0;
+      #endif
     };
     #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
     typedef class experimental_async_interface async_interface;
@@ -98,6 +114,9 @@
     virtual ::grpc::ClientAsyncResponseReaderInterface< ::dmi::ListEventsResponse>* PrepareAsyncListEventsRaw(::grpc::ClientContext* context, const ::dmi::HardwareID& request, ::grpc::CompletionQueue* cq) = 0;
     virtual ::grpc::ClientAsyncResponseReaderInterface< ::dmi::EventsConfigurationResponse>* AsyncUpdateEventsConfigurationRaw(::grpc::ClientContext* context, const ::dmi::EventsConfigurationRequest& request, ::grpc::CompletionQueue* cq) = 0;
     virtual ::grpc::ClientAsyncResponseReaderInterface< ::dmi::EventsConfigurationResponse>* PrepareAsyncUpdateEventsConfigurationRaw(::grpc::ClientContext* context, const ::dmi::EventsConfigurationRequest& request, ::grpc::CompletionQueue* cq) = 0;
+    virtual ::grpc::ClientReaderInterface< ::dmi::Event>* StreamEventsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) = 0;
+    virtual ::grpc::ClientAsyncReaderInterface< ::dmi::Event>* AsyncStreamEventsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) = 0;
+    virtual ::grpc::ClientAsyncReaderInterface< ::dmi::Event>* PrepareAsyncStreamEventsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0;
   };
   class Stub final : public StubInterface {
    public:
@@ -116,6 +135,15 @@
     std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::dmi::EventsConfigurationResponse>> PrepareAsyncUpdateEventsConfiguration(::grpc::ClientContext* context, const ::dmi::EventsConfigurationRequest& request, ::grpc::CompletionQueue* cq) {
       return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::dmi::EventsConfigurationResponse>>(PrepareAsyncUpdateEventsConfigurationRaw(context, request, cq));
     }
+    std::unique_ptr< ::grpc::ClientReader< ::dmi::Event>> StreamEvents(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) {
+      return std::unique_ptr< ::grpc::ClientReader< ::dmi::Event>>(StreamEventsRaw(context, request));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncReader< ::dmi::Event>> AsyncStreamEvents(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) {
+      return std::unique_ptr< ::grpc::ClientAsyncReader< ::dmi::Event>>(AsyncStreamEventsRaw(context, request, cq, tag));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncReader< ::dmi::Event>> PrepareAsyncStreamEvents(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncReader< ::dmi::Event>>(PrepareAsyncStreamEventsRaw(context, request, cq));
+    }
     class experimental_async final :
       public StubInterface::experimental_async_interface {
      public:
@@ -143,6 +171,11 @@
       #else
       void UpdateEventsConfiguration(::grpc::ClientContext* context, const ::grpc::ByteBuffer* request, ::dmi::EventsConfigurationResponse* response, ::grpc::experimental::ClientUnaryReactor* reactor) override;
       #endif
+      #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      void StreamEvents(::grpc::ClientContext* context, ::google::protobuf::Empty* request, ::grpc::ClientReadReactor< ::dmi::Event>* reactor) override;
+      #else
+      void StreamEvents(::grpc::ClientContext* context, ::google::protobuf::Empty* request, ::grpc::experimental::ClientReadReactor< ::dmi::Event>* reactor) override;
+      #endif
      private:
       friend class Stub;
       explicit experimental_async(Stub* stub): stub_(stub) { }
@@ -158,8 +191,12 @@
     ::grpc::ClientAsyncResponseReader< ::dmi::ListEventsResponse>* PrepareAsyncListEventsRaw(::grpc::ClientContext* context, const ::dmi::HardwareID& request, ::grpc::CompletionQueue* cq) override;
     ::grpc::ClientAsyncResponseReader< ::dmi::EventsConfigurationResponse>* AsyncUpdateEventsConfigurationRaw(::grpc::ClientContext* context, const ::dmi::EventsConfigurationRequest& request, ::grpc::CompletionQueue* cq) override;
     ::grpc::ClientAsyncResponseReader< ::dmi::EventsConfigurationResponse>* PrepareAsyncUpdateEventsConfigurationRaw(::grpc::ClientContext* context, const ::dmi::EventsConfigurationRequest& request, ::grpc::CompletionQueue* cq) override;
+    ::grpc::ClientReader< ::dmi::Event>* StreamEventsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) override;
+    ::grpc::ClientAsyncReader< ::dmi::Event>* AsyncStreamEventsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) override;
+    ::grpc::ClientAsyncReader< ::dmi::Event>* PrepareAsyncStreamEventsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override;
     const ::grpc::internal::RpcMethod rpcmethod_ListEvents_;
     const ::grpc::internal::RpcMethod rpcmethod_UpdateEventsConfiguration_;
+    const ::grpc::internal::RpcMethod rpcmethod_StreamEvents_;
   };
   static std::unique_ptr<Stub> NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
 
@@ -173,6 +210,8 @@
     // The default behavior of the device is to report all the supported events

     // This configuration is persisted across reboots of the device or the device manager

     virtual ::grpc::Status UpdateEventsConfiguration(::grpc::ServerContext* context, const ::dmi::EventsConfigurationRequest* request, ::dmi::EventsConfigurationResponse* response);
+    // Initiate the server streaming of the events

+    virtual ::grpc::Status StreamEvents(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::grpc::ServerWriter< ::dmi::Event>* writer);
   };
   template <class BaseClass>
   class WithAsyncMethod_ListEvents : public BaseClass {
@@ -214,7 +253,27 @@
       ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag);
     }
   };
-  typedef WithAsyncMethod_ListEvents<WithAsyncMethod_UpdateEventsConfiguration<Service > > AsyncService;
+  template <class BaseClass>
+  class WithAsyncMethod_StreamEvents : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithAsyncMethod_StreamEvents() {
+      ::grpc::Service::MarkMethodAsync(2);
+    }
+    ~WithAsyncMethod_StreamEvents() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status StreamEvents(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::grpc::ServerWriter< ::dmi::Event>* /*writer*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestStreamEvents(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncWriter< ::dmi::Event>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncServerStreaming(2, context, request, writer, new_call_cq, notification_cq, tag);
+    }
+  };
+  typedef WithAsyncMethod_ListEvents<WithAsyncMethod_UpdateEventsConfiguration<WithAsyncMethod_StreamEvents<Service > > > AsyncService;
   template <class BaseClass>
   class ExperimentalWithCallbackMethod_ListEvents : public BaseClass {
    private:
@@ -309,11 +368,49 @@
     #endif
       { return nullptr; }
   };
+  template <class BaseClass>
+  class ExperimentalWithCallbackMethod_StreamEvents : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    ExperimentalWithCallbackMethod_StreamEvents() {
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      ::grpc::Service::
+    #else
+      ::grpc::Service::experimental().
+    #endif
+        MarkMethodCallback(2,
+          new ::grpc_impl::internal::CallbackServerStreamingHandler< ::google::protobuf::Empty, ::dmi::Event>(
+            [this](
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+                   ::grpc::CallbackServerContext*
+    #else
+                   ::grpc::experimental::CallbackServerContext*
+    #endif
+                     context, const ::google::protobuf::Empty* request) { return this->StreamEvents(context, request); }));
+    }
+    ~ExperimentalWithCallbackMethod_StreamEvents() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status StreamEvents(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::grpc::ServerWriter< ::dmi::Event>* /*writer*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+    virtual ::grpc::ServerWriteReactor< ::dmi::Event>* StreamEvents(
+      ::grpc::CallbackServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/)
+    #else
+    virtual ::grpc::experimental::ServerWriteReactor< ::dmi::Event>* StreamEvents(
+      ::grpc::experimental::CallbackServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/)
+    #endif
+      { return nullptr; }
+  };
   #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
-  typedef ExperimentalWithCallbackMethod_ListEvents<ExperimentalWithCallbackMethod_UpdateEventsConfiguration<Service > > CallbackService;
+  typedef ExperimentalWithCallbackMethod_ListEvents<ExperimentalWithCallbackMethod_UpdateEventsConfiguration<ExperimentalWithCallbackMethod_StreamEvents<Service > > > CallbackService;
   #endif
 
-  typedef ExperimentalWithCallbackMethod_ListEvents<ExperimentalWithCallbackMethod_UpdateEventsConfiguration<Service > > ExperimentalCallbackService;
+  typedef ExperimentalWithCallbackMethod_ListEvents<ExperimentalWithCallbackMethod_UpdateEventsConfiguration<ExperimentalWithCallbackMethod_StreamEvents<Service > > > ExperimentalCallbackService;
   template <class BaseClass>
   class WithGenericMethod_ListEvents : public BaseClass {
    private:
@@ -349,6 +446,23 @@
     }
   };
   template <class BaseClass>
+  class WithGenericMethod_StreamEvents : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithGenericMethod_StreamEvents() {
+      ::grpc::Service::MarkMethodGeneric(2);
+    }
+    ~WithGenericMethod_StreamEvents() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status StreamEvents(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::grpc::ServerWriter< ::dmi::Event>* /*writer*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+  };
+  template <class BaseClass>
   class WithRawMethod_ListEvents : public BaseClass {
    private:
     void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
@@ -389,6 +503,26 @@
     }
   };
   template <class BaseClass>
+  class WithRawMethod_StreamEvents : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawMethod_StreamEvents() {
+      ::grpc::Service::MarkMethodRaw(2);
+    }
+    ~WithRawMethod_StreamEvents() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status StreamEvents(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::grpc::ServerWriter< ::dmi::Event>* /*writer*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestStreamEvents(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncWriter< ::grpc::ByteBuffer>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncServerStreaming(2, context, request, writer, new_call_cq, notification_cq, tag);
+    }
+  };
+  template <class BaseClass>
   class ExperimentalWithRawCallbackMethod_ListEvents : public BaseClass {
    private:
     void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
@@ -465,6 +599,44 @@
       { return nullptr; }
   };
   template <class BaseClass>
+  class ExperimentalWithRawCallbackMethod_StreamEvents : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    ExperimentalWithRawCallbackMethod_StreamEvents() {
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      ::grpc::Service::
+    #else
+      ::grpc::Service::experimental().
+    #endif
+        MarkMethodRawCallback(2,
+          new ::grpc_impl::internal::CallbackServerStreamingHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>(
+            [this](
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+                   ::grpc::CallbackServerContext*
+    #else
+                   ::grpc::experimental::CallbackServerContext*
+    #endif
+                     context, const::grpc::ByteBuffer* request) { return this->StreamEvents(context, request); }));
+    }
+    ~ExperimentalWithRawCallbackMethod_StreamEvents() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status StreamEvents(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::grpc::ServerWriter< ::dmi::Event>* /*writer*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+    virtual ::grpc::ServerWriteReactor< ::grpc::ByteBuffer>* StreamEvents(
+      ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/)
+    #else
+    virtual ::grpc::experimental::ServerWriteReactor< ::grpc::ByteBuffer>* StreamEvents(
+      ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/)
+    #endif
+      { return nullptr; }
+  };
+  template <class BaseClass>
   class WithStreamedUnaryMethod_ListEvents : public BaseClass {
    private:
     void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
@@ -519,8 +691,35 @@
     virtual ::grpc::Status StreamedUpdateEventsConfiguration(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::dmi::EventsConfigurationRequest,::dmi::EventsConfigurationResponse>* server_unary_streamer) = 0;
   };
   typedef WithStreamedUnaryMethod_ListEvents<WithStreamedUnaryMethod_UpdateEventsConfiguration<Service > > StreamedUnaryService;
-  typedef Service SplitStreamedService;
-  typedef WithStreamedUnaryMethod_ListEvents<WithStreamedUnaryMethod_UpdateEventsConfiguration<Service > > StreamedService;
+  template <class BaseClass>
+  class WithSplitStreamingMethod_StreamEvents : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithSplitStreamingMethod_StreamEvents() {
+      ::grpc::Service::MarkMethodStreamed(2,
+        new ::grpc::internal::SplitServerStreamingHandler<
+          ::google::protobuf::Empty, ::dmi::Event>(
+            [this](::grpc_impl::ServerContext* context,
+                   ::grpc_impl::ServerSplitStreamer<
+                     ::google::protobuf::Empty, ::dmi::Event>* streamer) {
+                       return this->StreamedStreamEvents(context,
+                         streamer);
+                  }));
+    }
+    ~WithSplitStreamingMethod_StreamEvents() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable regular version of this method
+    ::grpc::Status StreamEvents(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::grpc::ServerWriter< ::dmi::Event>* /*writer*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    // replace default version of method with split streamed
+    virtual ::grpc::Status StreamedStreamEvents(::grpc::ServerContext* context, ::grpc::ServerSplitStreamer< ::google::protobuf::Empty,::dmi::Event>* server_split_streamer) = 0;
+  };
+  typedef WithSplitStreamingMethod_StreamEvents<Service > SplitStreamedService;
+  typedef WithStreamedUnaryMethod_ListEvents<WithStreamedUnaryMethod_UpdateEventsConfiguration<WithSplitStreamingMethod_StreamEvents<Service > > > StreamedService;
 };
 
 }  // namespace dmi
diff --git a/cpp/dmi/hw_events_mgmt_service.pb.cc b/cpp/dmi/hw_events_mgmt_service.pb.cc
index 4f856f0..28a38bc 100644
--- a/cpp/dmi/hw_events_mgmt_service.pb.cc
+++ b/cpp/dmi/hw_events_mgmt_service.pb.cc
@@ -391,112 +391,115 @@
 const char descriptor_table_protodef_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto[] =
   "\n dmi/hw_events_mgmt_service.proto\022\003dmi\032"
   "\021dmi/commons.proto\032\014dmi/hw.proto\032\037google"
-  "/protobuf/timestamp.proto\"N\n\tValueType\022\021"
-  "\n\007int_val\030\001 \001(\003H\000\022\022\n\010uint_val\030\002 \001(\004H\000\022\023\n"
-  "\tfloat_val\030\003 \001(\002H\000B\005\n\003val\"G\n\nWaterMarks\022"
-  "\034\n\004high\030\001 \001(\0132\016.dmi.ValueType\022\033\n\003low\030\002 \001"
-  "(\0132\016.dmi.ValueType\"]\n\nThresholds\022 \n\005uppe"
-  "r\030\001 \001(\0132\017.dmi.WaterMarksH\000\022 \n\005lower\030\002 \001("
-  "\0132\017.dmi.WaterMarksH\000B\013\n\tthreshold\"c\n\024Thr"
-  "esholdInformation\022&\n\016observed_value\030\001 \001("
-  "\0132\016.dmi.ValueType\022#\n\nthresholds\030\002 \001(\0132\017."
-  "dmi.Thresholds\"g\n\010EventCfg\022\037\n\010event_id\030\001"
-  " \001(\0162\r.dmi.EventIds\022\025\n\ris_configured\030\002 \001"
-  "(\010\022#\n\nthresholds\030\003 \001(\0132\017.dmi.Thresholds\""
-  ")\n\tEventsCfg\022\034\n\005items\030\001 \003(\0132\r.dmi.EventC"
-  "fg\"\370\001\n\022ListEventsResponse\022\033\n\006status\030\001 \001("
-  "\0162\013.dmi.Status\022.\n\006reason\030\002 \001(\0162\036.dmi.Lis"
-  "tEventsResponse.Reason\022\036\n\006events\030\003 \001(\0132\016"
-  ".dmi.EventsCfg\022\025\n\rreason_detail\030\004 \001(\t\"^\n"
-  "\006Reason\022\024\n\020UNDEFINED_REASON\020\000\022\022\n\016UNKNOWN"
-  "_DEVICE\020\001\022\022\n\016INTERNAL_ERROR\020\002\022\026\n\022DEVICE_"
-  "UNREACHABLE\020\003\"\210\001\n\032EventsConfigurationReq"
-  "uest\022\036\n\013device_uuid\030\001 \001(\0132\t.dmi.Uuid\022!\n\007"
-  "changes\030\002 \001(\0132\016.dmi.EventsCfgH\000\022\032\n\020reset"
-  "_to_default\030\003 \001(\010H\000B\013\n\toperation\"\376\001\n\033Eve"
-  "ntsConfigurationResponse\022\033\n\006status\030\001 \001(\016"
-  "2\013.dmi.Status\0227\n\006reason\030\002 \001(\0162\'.dmi.Even"
-  "tsConfigurationResponse.Reason\022\025\n\rreason"
-  "_detail\030\003 \001(\t\"r\n\006Reason\022\024\n\020UNDEFINED_REA"
-  "SON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERNAL_ER"
-  "ROR\020\002\022\022\n\016INVALID_CONFIG\020\003\022\026\n\022DEVICE_UNRE"
-  "ACHABLE\020\004\"j\n\rEventMetaData\022\036\n\013device_uui"
-  "d\030\001 \001(\0132\t.dmi.Uuid\022!\n\016component_uuid\030\002 \001"
-  "(\0132\t.dmi.Uuid\022\026\n\016component_name\030\003 \001(\t\"\310\001"
-  "\n\005Event\022*\n\016event_metadata\030\001 \001(\0132\022.dmi.Ev"
-  "entMetaData\022\037\n\010event_id\030\002 \001(\0162\r.dmi.Even"
-  "tIds\022-\n\traised_ts\030\003 \001(\0132\032.google.protobu"
-  "f.Timestamp\0221\n\016threshold_info\030\004 \001(\0132\031.dm"
-  "i.ThresholdInformation\022\020\n\010add_info\030\005 \001(\t"
-  "*\321\016\n\010EventIds\022\030\n\024EVENT_NAME_UNDEFINED\020\000\022"
-  "\036\n\032EVENT_TRANSCEIVER_PLUG_OUT\020d\022\035\n\031EVENT"
-  "_TRANSCEIVER_PLUG_IN\020e\022-\n)EVENT_TRANSCEI"
-  "VER_VOLTAGE_ABOVE_THRESHOLD\020f\022-\n)EVENT_T"
-  "RANSCEIVER_VOLTAGE_BELOW_THRESHOLD\020g\0221\n-"
-  "EVENT_TRANSCEIVER_TEMPERATURE_ABOVE_THRE"
-  "SHOLD\020h\0221\n-EVENT_TRANSCEIVER_TEMPERATURE"
-  "_BELOW_THRESHOLD\020i\022-\n)EVENT_TRANSCEIVER_"
-  "CURRENT_ABOVE_THRESHOLD\020j\022-\n)EVENT_TRANS"
-  "CEIVER_CURRENT_BELOW_THRESHOLD\020k\022.\n*EVEN"
-  "T_TRANSCEIVER_RX_POWER_ABOVE_THRESHOLD\020l"
-  "\022.\n*EVENT_TRANSCEIVER_RX_POWER_BELOW_THR"
-  "ESHOLD\020m\022.\n*EVENT_TRANSCEIVER_TX_POWER_A"
-  "BOVE_THRESHOLD\020n\022.\n*EVENT_TRANSCEIVER_TX"
-  "_POWER_BELOW_THRESHOLD\020o\022\035\n\031EVENT_TRANSC"
-  "EIVER_FAILURE\020p\0227\n3EVENT_TRANSCEIVER_VOL"
-  "TAGE_ABOVE_THRESHOLD_RECOVERED\020q\0227\n3EVEN"
-  "T_TRANSCEIVER_VOLTAGE_BELOW_THRESHOLD_RE"
-  "COVERED\020r\022;\n7EVENT_TRANSCEIVER_TEMPERATU"
-  "RE_ABOVE_THRESHOLD_RECOVERED\020s\022;\n7EVENT_"
-  "TRANSCEIVER_TEMPERATURE_BELOW_THRESHOLD_"
-  "RECOVERED\020t\0227\n3EVENT_TRANSCEIVER_CURRENT"
-  "_ABOVE_THRESHOLD_RECOVERED\020u\0227\n3EVENT_TR"
-  "ANSCEIVER_CURRENT_BELOW_THRESHOLD_RECOVE"
-  "RED\020v\0228\n4EVENT_TRANSCEIVER_RX_POWER_ABOV"
-  "E_THRESHOLD_RECOVERED\020w\0228\n4EVENT_TRANSCE"
-  "IVER_RX_POWER_BELOW_THRESHOLD_RECOVERED\020"
-  "x\0228\n4EVENT_TRANSCEIVER_TX_POWER_ABOVE_TH"
-  "RESHOLD_RECOVERED\020y\0228\n4EVENT_TRANSCEIVER"
-  "_TX_POWER_BELOW_THRESHOLD_RECOVERED\020z\022\'\n"
-  "#EVENT_TRANSCEIVER_FAILURE_RECOVERED\020{\022\027"
-  "\n\022EVENT_PSU_PLUG_OUT\020\310\001\022\026\n\021EVENT_PSU_PLU"
-  "G_IN\020\311\001\022\026\n\021EVENT_PSU_FAILURE\020\312\001\022 \n\033EVENT"
-  "_PSU_FAILURE_RECOVERED\020\313\001\022\026\n\021EVENT_FAN_F"
-  "AILURE\020\254\002\022\027\n\022EVENT_FAN_PLUG_OUT\020\255\002\022\026\n\021EV"
-  "ENT_FAN_PLUG_IN\020\256\002\022 \n\033EVENT_FAN_FAILURE_"
-  "RECOVERED\020\257\002\022)\n$EVENT_CPU_TEMPERATURE_AB"
-  "OVE_CRITICAL\020\220\003\022&\n!EVENT_CPU_TEMPERATURE"
-  "_ABOVE_FATAL\020\221\003\0223\n.EVENT_CPU_TEMPERATURE"
-  "_ABOVE_CRITICAL_RECOVERED\020\222\003\0220\n+EVENT_CP"
-  "U_TEMPERATURE_ABOVE_FATAL_RECOVERED\020\223\003\022\032"
-  "\n\025EVENT_HW_DEVICE_RESET\020\364\003\022/\n*EVENT_HW_D"
-  "EVICE_TEMPERATURE_ABOVE_CRITICAL\020\365\003\022,\n\'E"
-  "VENT_HW_DEVICE_TEMPERATURE_ABOVE_FATAL\020\366"
-  "\003\0229\n4EVENT_HW_DEVICE_TEMPERATURE_ABOVE_C"
-  "RITICAL_RECOVERED\020\367\003\0226\n1EVENT_HW_DEVICE_"
-  "TEMPERATURE_ABOVE_FATAL_RECOVERED\020\370\0032\267\001\n"
-  "\035NativeEventsManagementService\0226\n\nListEv"
-  "ents\022\017.dmi.HardwareID\032\027.dmi.ListEventsRe"
-  "sponse\022^\n\031UpdateEventsConfiguration\022\037.dm"
-  "i.EventsConfigurationRequest\032 .dmi.Event"
-  "sConfigurationResponseB;Z9github.com/ope"
-  "ncord/device-management-interface/v3/go/"
-  "dmib\006proto3"
+  "/protobuf/timestamp.proto\032\033google/protob"
+  "uf/empty.proto\"N\n\tValueType\022\021\n\007int_val\030\001"
+  " \001(\003H\000\022\022\n\010uint_val\030\002 \001(\004H\000\022\023\n\tfloat_val\030"
+  "\003 \001(\002H\000B\005\n\003val\"G\n\nWaterMarks\022\034\n\004high\030\001 \001"
+  "(\0132\016.dmi.ValueType\022\033\n\003low\030\002 \001(\0132\016.dmi.Va"
+  "lueType\"]\n\nThresholds\022 \n\005upper\030\001 \001(\0132\017.d"
+  "mi.WaterMarksH\000\022 \n\005lower\030\002 \001(\0132\017.dmi.Wat"
+  "erMarksH\000B\013\n\tthreshold\"c\n\024ThresholdInfor"
+  "mation\022&\n\016observed_value\030\001 \001(\0132\016.dmi.Val"
+  "ueType\022#\n\nthresholds\030\002 \001(\0132\017.dmi.Thresho"
+  "lds\"g\n\010EventCfg\022\037\n\010event_id\030\001 \001(\0162\r.dmi."
+  "EventIds\022\025\n\ris_configured\030\002 \001(\010\022#\n\nthres"
+  "holds\030\003 \001(\0132\017.dmi.Thresholds\")\n\tEventsCf"
+  "g\022\034\n\005items\030\001 \003(\0132\r.dmi.EventCfg\"\370\001\n\022List"
+  "EventsResponse\022\033\n\006status\030\001 \001(\0162\013.dmi.Sta"
+  "tus\022.\n\006reason\030\002 \001(\0162\036.dmi.ListEventsResp"
+  "onse.Reason\022\036\n\006events\030\003 \001(\0132\016.dmi.Events"
+  "Cfg\022\025\n\rreason_detail\030\004 \001(\t\"^\n\006Reason\022\024\n\020"
+  "UNDEFINED_REASON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022"
+  "\n\016INTERNAL_ERROR\020\002\022\026\n\022DEVICE_UNREACHABLE"
+  "\020\003\"\210\001\n\032EventsConfigurationRequest\022\036\n\013dev"
+  "ice_uuid\030\001 \001(\0132\t.dmi.Uuid\022!\n\007changes\030\002 \001"
+  "(\0132\016.dmi.EventsCfgH\000\022\032\n\020reset_to_default"
+  "\030\003 \001(\010H\000B\013\n\toperation\"\376\001\n\033EventsConfigur"
+  "ationResponse\022\033\n\006status\030\001 \001(\0162\013.dmi.Stat"
+  "us\0227\n\006reason\030\002 \001(\0162\'.dmi.EventsConfigura"
+  "tionResponse.Reason\022\025\n\rreason_detail\030\003 \001"
+  "(\t\"r\n\006Reason\022\024\n\020UNDEFINED_REASON\020\000\022\022\n\016UN"
+  "KNOWN_DEVICE\020\001\022\022\n\016INTERNAL_ERROR\020\002\022\022\n\016IN"
+  "VALID_CONFIG\020\003\022\026\n\022DEVICE_UNREACHABLE\020\004\"j"
+  "\n\rEventMetaData\022\036\n\013device_uuid\030\001 \001(\0132\t.d"
+  "mi.Uuid\022!\n\016component_uuid\030\002 \001(\0132\t.dmi.Uu"
+  "id\022\026\n\016component_name\030\003 \001(\t\"\310\001\n\005Event\022*\n\016"
+  "event_metadata\030\001 \001(\0132\022.dmi.EventMetaData"
+  "\022\037\n\010event_id\030\002 \001(\0162\r.dmi.EventIds\022-\n\trai"
+  "sed_ts\030\003 \001(\0132\032.google.protobuf.Timestamp"
+  "\0221\n\016threshold_info\030\004 \001(\0132\031.dmi.Threshold"
+  "Information\022\020\n\010add_info\030\005 \001(\t*\321\016\n\010EventI"
+  "ds\022\030\n\024EVENT_NAME_UNDEFINED\020\000\022\036\n\032EVENT_TR"
+  "ANSCEIVER_PLUG_OUT\020d\022\035\n\031EVENT_TRANSCEIVE"
+  "R_PLUG_IN\020e\022-\n)EVENT_TRANSCEIVER_VOLTAGE"
+  "_ABOVE_THRESHOLD\020f\022-\n)EVENT_TRANSCEIVER_"
+  "VOLTAGE_BELOW_THRESHOLD\020g\0221\n-EVENT_TRANS"
+  "CEIVER_TEMPERATURE_ABOVE_THRESHOLD\020h\0221\n-"
+  "EVENT_TRANSCEIVER_TEMPERATURE_BELOW_THRE"
+  "SHOLD\020i\022-\n)EVENT_TRANSCEIVER_CURRENT_ABO"
+  "VE_THRESHOLD\020j\022-\n)EVENT_TRANSCEIVER_CURR"
+  "ENT_BELOW_THRESHOLD\020k\022.\n*EVENT_TRANSCEIV"
+  "ER_RX_POWER_ABOVE_THRESHOLD\020l\022.\n*EVENT_T"
+  "RANSCEIVER_RX_POWER_BELOW_THRESHOLD\020m\022.\n"
+  "*EVENT_TRANSCEIVER_TX_POWER_ABOVE_THRESH"
+  "OLD\020n\022.\n*EVENT_TRANSCEIVER_TX_POWER_BELO"
+  "W_THRESHOLD\020o\022\035\n\031EVENT_TRANSCEIVER_FAILU"
+  "RE\020p\0227\n3EVENT_TRANSCEIVER_VOLTAGE_ABOVE_"
+  "THRESHOLD_RECOVERED\020q\0227\n3EVENT_TRANSCEIV"
+  "ER_VOLTAGE_BELOW_THRESHOLD_RECOVERED\020r\022;"
+  "\n7EVENT_TRANSCEIVER_TEMPERATURE_ABOVE_TH"
+  "RESHOLD_RECOVERED\020s\022;\n7EVENT_TRANSCEIVER"
+  "_TEMPERATURE_BELOW_THRESHOLD_RECOVERED\020t"
+  "\0227\n3EVENT_TRANSCEIVER_CURRENT_ABOVE_THRE"
+  "SHOLD_RECOVERED\020u\0227\n3EVENT_TRANSCEIVER_C"
+  "URRENT_BELOW_THRESHOLD_RECOVERED\020v\0228\n4EV"
+  "ENT_TRANSCEIVER_RX_POWER_ABOVE_THRESHOLD"
+  "_RECOVERED\020w\0228\n4EVENT_TRANSCEIVER_RX_POW"
+  "ER_BELOW_THRESHOLD_RECOVERED\020x\0228\n4EVENT_"
+  "TRANSCEIVER_TX_POWER_ABOVE_THRESHOLD_REC"
+  "OVERED\020y\0228\n4EVENT_TRANSCEIVER_TX_POWER_B"
+  "ELOW_THRESHOLD_RECOVERED\020z\022\'\n#EVENT_TRAN"
+  "SCEIVER_FAILURE_RECOVERED\020{\022\027\n\022EVENT_PSU"
+  "_PLUG_OUT\020\310\001\022\026\n\021EVENT_PSU_PLUG_IN\020\311\001\022\026\n\021"
+  "EVENT_PSU_FAILURE\020\312\001\022 \n\033EVENT_PSU_FAILUR"
+  "E_RECOVERED\020\313\001\022\026\n\021EVENT_FAN_FAILURE\020\254\002\022\027"
+  "\n\022EVENT_FAN_PLUG_OUT\020\255\002\022\026\n\021EVENT_FAN_PLU"
+  "G_IN\020\256\002\022 \n\033EVENT_FAN_FAILURE_RECOVERED\020\257"
+  "\002\022)\n$EVENT_CPU_TEMPERATURE_ABOVE_CRITICA"
+  "L\020\220\003\022&\n!EVENT_CPU_TEMPERATURE_ABOVE_FATA"
+  "L\020\221\003\0223\n.EVENT_CPU_TEMPERATURE_ABOVE_CRIT"
+  "ICAL_RECOVERED\020\222\003\0220\n+EVENT_CPU_TEMPERATU"
+  "RE_ABOVE_FATAL_RECOVERED\020\223\003\022\032\n\025EVENT_HW_"
+  "DEVICE_RESET\020\364\003\022/\n*EVENT_HW_DEVICE_TEMPE"
+  "RATURE_ABOVE_CRITICAL\020\365\003\022,\n\'EVENT_HW_DEV"
+  "ICE_TEMPERATURE_ABOVE_FATAL\020\366\003\0229\n4EVENT_"
+  "HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL_REC"
+  "OVERED\020\367\003\0226\n1EVENT_HW_DEVICE_TEMPERATURE"
+  "_ABOVE_FATAL_RECOVERED\020\370\0032\355\001\n\035NativeEven"
+  "tsManagementService\0226\n\nListEvents\022\017.dmi."
+  "HardwareID\032\027.dmi.ListEventsResponse\022^\n\031U"
+  "pdateEventsConfiguration\022\037.dmi.EventsCon"
+  "figurationRequest\032 .dmi.EventsConfigurat"
+  "ionResponse\0224\n\014StreamEvents\022\026.google.pro"
+  "tobuf.Empty\032\n.dmi.Event0\001B;Z9github.com/"
+  "opencord/device-management-interface/v3/"
+  "go/dmib\006proto3"
   ;
 ::google::protobuf::internal::DescriptorTable descriptor_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto = {
   false, InitDefaults_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto, 
   descriptor_table_protodef_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto,
-  "dmi/hw_events_mgmt_service.proto", &assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto, 3691,
+  "dmi/hw_events_mgmt_service.proto", &assign_descriptors_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto, 3774,
 };
 
 void AddDescriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto() {
-  static constexpr ::google::protobuf::internal::InitFunc deps[3] =
+  static constexpr ::google::protobuf::internal::InitFunc deps[4] =
   {
     ::AddDescriptors_dmi_2fcommons_2eproto,
     ::AddDescriptors_dmi_2fhw_2eproto,
     ::AddDescriptors_google_2fprotobuf_2ftimestamp_2eproto,
+    ::AddDescriptors_google_2fprotobuf_2fempty_2eproto,
   };
- ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto, deps, 3);
+ ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto, deps, 4);
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
diff --git a/cpp/dmi/hw_events_mgmt_service.pb.h b/cpp/dmi/hw_events_mgmt_service.pb.h
index 472a6a9..4f6cf5a 100644
--- a/cpp/dmi/hw_events_mgmt_service.pb.h
+++ b/cpp/dmi/hw_events_mgmt_service.pb.h
@@ -35,6 +35,7 @@
 #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
diff --git a/cpp/dmi/hw_metrics_mgmt_service.grpc.pb.cc b/cpp/dmi/hw_metrics_mgmt_service.grpc.pb.cc
index 1c674c4..a35f91e 100644
--- a/cpp/dmi/hw_metrics_mgmt_service.grpc.pb.cc
+++ b/cpp/dmi/hw_metrics_mgmt_service.grpc.pb.cc
@@ -25,6 +25,7 @@
   "/dmi.NativeMetricsManagementService/ListMetrics",
   "/dmi.NativeMetricsManagementService/UpdateMetricsConfiguration",
   "/dmi.NativeMetricsManagementService/GetMetric",
+  "/dmi.NativeMetricsManagementService/StreamMetrics",
 };
 
 std::unique_ptr< NativeMetricsManagementService::Stub> NativeMetricsManagementService::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) {
@@ -37,6 +38,7 @@
   : channel_(channel), rpcmethod_ListMetrics_(NativeMetricsManagementService_method_names[0], ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
   , rpcmethod_UpdateMetricsConfiguration_(NativeMetricsManagementService_method_names[1], ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
   , rpcmethod_GetMetric_(NativeMetricsManagementService_method_names[2], ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
+  , rpcmethod_StreamMetrics_(NativeMetricsManagementService_method_names[3], ::grpc::internal::RpcMethod::SERVER_STREAMING, channel)
   {}
 
 ::grpc::Status NativeMetricsManagementService::Stub::ListMetrics(::grpc::ClientContext* context, const ::dmi::HardwareID& request, ::dmi::ListMetricsResponse* response) {
@@ -123,6 +125,22 @@
   return ::grpc_impl::internal::ClientAsyncResponseReaderFactory< ::dmi::GetMetricResponse>::Create(channel_.get(), cq, rpcmethod_GetMetric_, context, request, false);
 }
 
+::grpc::ClientReader< ::dmi::Metric>* NativeMetricsManagementService::Stub::StreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) {
+  return ::grpc_impl::internal::ClientReaderFactory< ::dmi::Metric>::Create(channel_.get(), rpcmethod_StreamMetrics_, context, request);
+}
+
+void NativeMetricsManagementService::Stub::experimental_async::StreamMetrics(::grpc::ClientContext* context, ::google::protobuf::Empty* request, ::grpc::experimental::ClientReadReactor< ::dmi::Metric>* reactor) {
+  ::grpc_impl::internal::ClientCallbackReaderFactory< ::dmi::Metric>::Create(stub_->channel_.get(), stub_->rpcmethod_StreamMetrics_, context, request, reactor);
+}
+
+::grpc::ClientAsyncReader< ::dmi::Metric>* NativeMetricsManagementService::Stub::AsyncStreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) {
+  return ::grpc_impl::internal::ClientAsyncReaderFactory< ::dmi::Metric>::Create(channel_.get(), cq, rpcmethod_StreamMetrics_, context, request, true, tag);
+}
+
+::grpc::ClientAsyncReader< ::dmi::Metric>* NativeMetricsManagementService::Stub::PrepareAsyncStreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) {
+  return ::grpc_impl::internal::ClientAsyncReaderFactory< ::dmi::Metric>::Create(channel_.get(), cq, rpcmethod_StreamMetrics_, context, request, false, nullptr);
+}
+
 NativeMetricsManagementService::Service::Service() {
   AddMethod(new ::grpc::internal::RpcServiceMethod(
       NativeMetricsManagementService_method_names[0],
@@ -154,6 +172,16 @@
              ::dmi::GetMetricResponse* resp) {
                return service->GetMetric(ctx, req, resp);
              }, this)));
+  AddMethod(new ::grpc::internal::RpcServiceMethod(
+      NativeMetricsManagementService_method_names[3],
+      ::grpc::internal::RpcMethod::SERVER_STREAMING,
+      new ::grpc::internal::ServerStreamingHandler< NativeMetricsManagementService::Service, ::google::protobuf::Empty, ::dmi::Metric>(
+          [](NativeMetricsManagementService::Service* service,
+             ::grpc_impl::ServerContext* ctx,
+             const ::google::protobuf::Empty* req,
+             ::grpc_impl::ServerWriter<::dmi::Metric>* writer) {
+               return service->StreamMetrics(ctx, req, writer);
+             }, this)));
 }
 
 NativeMetricsManagementService::Service::~Service() {
@@ -180,6 +208,13 @@
   return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
 }
 
+::grpc::Status NativeMetricsManagementService::Service::StreamMetrics(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::grpc::ServerWriter< ::dmi::Metric>* writer) {
+  (void) context;
+  (void) request;
+  (void) writer;
+  return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+}
+
 
 }  // namespace dmi
 
diff --git a/cpp/dmi/hw_metrics_mgmt_service.grpc.pb.h b/cpp/dmi/hw_metrics_mgmt_service.grpc.pb.h
index 560b350..a96cbd7 100644
--- a/cpp/dmi/hw_metrics_mgmt_service.grpc.pb.h
+++ b/cpp/dmi/hw_metrics_mgmt_service.grpc.pb.h
@@ -66,6 +66,16 @@
     std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::dmi::GetMetricResponse>> PrepareAsyncGetMetric(::grpc::ClientContext* context, const ::dmi::GetMetricRequest& request, ::grpc::CompletionQueue* cq) {
       return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::dmi::GetMetricResponse>>(PrepareAsyncGetMetricRaw(context, request, cq));
     }
+    // Initiate the server streaming of the metrics

+    std::unique_ptr< ::grpc::ClientReaderInterface< ::dmi::Metric>> StreamMetrics(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) {
+      return std::unique_ptr< ::grpc::ClientReaderInterface< ::dmi::Metric>>(StreamMetricsRaw(context, request));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::dmi::Metric>> AsyncStreamMetrics(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) {
+      return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::dmi::Metric>>(AsyncStreamMetricsRaw(context, request, cq, tag));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::dmi::Metric>> PrepareAsyncStreamMetrics(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< ::dmi::Metric>>(PrepareAsyncStreamMetricsRaw(context, request, cq));
+    }
     class experimental_async_interface {
      public:
       virtual ~experimental_async_interface() {}
@@ -114,6 +124,12 @@
       #else
       virtual void GetMetric(::grpc::ClientContext* context, const ::grpc::ByteBuffer* request, ::dmi::GetMetricResponse* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0;
       #endif
+      // Initiate the server streaming of the metrics

+      #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      virtual void StreamMetrics(::grpc::ClientContext* context, ::google::protobuf::Empty* request, ::grpc::ClientReadReactor< ::dmi::Metric>* reactor) = 0;
+      #else
+      virtual void StreamMetrics(::grpc::ClientContext* context, ::google::protobuf::Empty* request, ::grpc::experimental::ClientReadReactor< ::dmi::Metric>* reactor) = 0;
+      #endif
     };
     #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
     typedef class experimental_async_interface async_interface;
@@ -129,6 +145,9 @@
     virtual ::grpc::ClientAsyncResponseReaderInterface< ::dmi::MetricsConfigurationResponse>* PrepareAsyncUpdateMetricsConfigurationRaw(::grpc::ClientContext* context, const ::dmi::MetricsConfigurationRequest& request, ::grpc::CompletionQueue* cq) = 0;
     virtual ::grpc::ClientAsyncResponseReaderInterface< ::dmi::GetMetricResponse>* AsyncGetMetricRaw(::grpc::ClientContext* context, const ::dmi::GetMetricRequest& request, ::grpc::CompletionQueue* cq) = 0;
     virtual ::grpc::ClientAsyncResponseReaderInterface< ::dmi::GetMetricResponse>* PrepareAsyncGetMetricRaw(::grpc::ClientContext* context, const ::dmi::GetMetricRequest& request, ::grpc::CompletionQueue* cq) = 0;
+    virtual ::grpc::ClientReaderInterface< ::dmi::Metric>* StreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) = 0;
+    virtual ::grpc::ClientAsyncReaderInterface< ::dmi::Metric>* AsyncStreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) = 0;
+    virtual ::grpc::ClientAsyncReaderInterface< ::dmi::Metric>* PrepareAsyncStreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0;
   };
   class Stub final : public StubInterface {
    public:
@@ -154,6 +173,15 @@
     std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::dmi::GetMetricResponse>> PrepareAsyncGetMetric(::grpc::ClientContext* context, const ::dmi::GetMetricRequest& request, ::grpc::CompletionQueue* cq) {
       return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::dmi::GetMetricResponse>>(PrepareAsyncGetMetricRaw(context, request, cq));
     }
+    std::unique_ptr< ::grpc::ClientReader< ::dmi::Metric>> StreamMetrics(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) {
+      return std::unique_ptr< ::grpc::ClientReader< ::dmi::Metric>>(StreamMetricsRaw(context, request));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncReader< ::dmi::Metric>> AsyncStreamMetrics(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) {
+      return std::unique_ptr< ::grpc::ClientAsyncReader< ::dmi::Metric>>(AsyncStreamMetricsRaw(context, request, cq, tag));
+    }
+    std::unique_ptr< ::grpc::ClientAsyncReader< ::dmi::Metric>> PrepareAsyncStreamMetrics(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) {
+      return std::unique_ptr< ::grpc::ClientAsyncReader< ::dmi::Metric>>(PrepareAsyncStreamMetricsRaw(context, request, cq));
+    }
     class experimental_async final :
       public StubInterface::experimental_async_interface {
      public:
@@ -193,6 +221,11 @@
       #else
       void GetMetric(::grpc::ClientContext* context, const ::grpc::ByteBuffer* request, ::dmi::GetMetricResponse* response, ::grpc::experimental::ClientUnaryReactor* reactor) override;
       #endif
+      #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      void StreamMetrics(::grpc::ClientContext* context, ::google::protobuf::Empty* request, ::grpc::ClientReadReactor< ::dmi::Metric>* reactor) override;
+      #else
+      void StreamMetrics(::grpc::ClientContext* context, ::google::protobuf::Empty* request, ::grpc::experimental::ClientReadReactor< ::dmi::Metric>* reactor) override;
+      #endif
      private:
       friend class Stub;
       explicit experimental_async(Stub* stub): stub_(stub) { }
@@ -210,9 +243,13 @@
     ::grpc::ClientAsyncResponseReader< ::dmi::MetricsConfigurationResponse>* PrepareAsyncUpdateMetricsConfigurationRaw(::grpc::ClientContext* context, const ::dmi::MetricsConfigurationRequest& request, ::grpc::CompletionQueue* cq) override;
     ::grpc::ClientAsyncResponseReader< ::dmi::GetMetricResponse>* AsyncGetMetricRaw(::grpc::ClientContext* context, const ::dmi::GetMetricRequest& request, ::grpc::CompletionQueue* cq) override;
     ::grpc::ClientAsyncResponseReader< ::dmi::GetMetricResponse>* PrepareAsyncGetMetricRaw(::grpc::ClientContext* context, const ::dmi::GetMetricRequest& request, ::grpc::CompletionQueue* cq) override;
+    ::grpc::ClientReader< ::dmi::Metric>* StreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request) override;
+    ::grpc::ClientAsyncReader< ::dmi::Metric>* AsyncStreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq, void* tag) override;
+    ::grpc::ClientAsyncReader< ::dmi::Metric>* PrepareAsyncStreamMetricsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override;
     const ::grpc::internal::RpcMethod rpcmethod_ListMetrics_;
     const ::grpc::internal::RpcMethod rpcmethod_UpdateMetricsConfiguration_;
     const ::grpc::internal::RpcMethod rpcmethod_GetMetric_;
+    const ::grpc::internal::RpcMethod rpcmethod_StreamMetrics_;
   };
   static std::unique_ptr<Stub> NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());
 
@@ -232,6 +269,8 @@
     virtual ::grpc::Status UpdateMetricsConfiguration(::grpc::ServerContext* context, const ::dmi::MetricsConfigurationRequest* request, ::dmi::MetricsConfigurationResponse* response);
     // Get the instantenous value of a metric

     virtual ::grpc::Status GetMetric(::grpc::ServerContext* context, const ::dmi::GetMetricRequest* request, ::dmi::GetMetricResponse* response);
+    // Initiate the server streaming of the metrics

+    virtual ::grpc::Status StreamMetrics(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::grpc::ServerWriter< ::dmi::Metric>* writer);
   };
   template <class BaseClass>
   class WithAsyncMethod_ListMetrics : public BaseClass {
@@ -293,7 +332,27 @@
       ::grpc::Service::RequestAsyncUnary(2, context, request, response, new_call_cq, notification_cq, tag);
     }
   };
-  typedef WithAsyncMethod_ListMetrics<WithAsyncMethod_UpdateMetricsConfiguration<WithAsyncMethod_GetMetric<Service > > > AsyncService;
+  template <class BaseClass>
+  class WithAsyncMethod_StreamMetrics : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithAsyncMethod_StreamMetrics() {
+      ::grpc::Service::MarkMethodAsync(3);
+    }
+    ~WithAsyncMethod_StreamMetrics() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status StreamMetrics(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::grpc::ServerWriter< ::dmi::Metric>* /*writer*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestStreamMetrics(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncWriter< ::dmi::Metric>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncServerStreaming(3, context, request, writer, new_call_cq, notification_cq, tag);
+    }
+  };
+  typedef WithAsyncMethod_ListMetrics<WithAsyncMethod_UpdateMetricsConfiguration<WithAsyncMethod_GetMetric<WithAsyncMethod_StreamMetrics<Service > > > > AsyncService;
   template <class BaseClass>
   class ExperimentalWithCallbackMethod_ListMetrics : public BaseClass {
    private:
@@ -435,11 +494,49 @@
     #endif
       { return nullptr; }
   };
+  template <class BaseClass>
+  class ExperimentalWithCallbackMethod_StreamMetrics : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    ExperimentalWithCallbackMethod_StreamMetrics() {
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      ::grpc::Service::
+    #else
+      ::grpc::Service::experimental().
+    #endif
+        MarkMethodCallback(3,
+          new ::grpc_impl::internal::CallbackServerStreamingHandler< ::google::protobuf::Empty, ::dmi::Metric>(
+            [this](
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+                   ::grpc::CallbackServerContext*
+    #else
+                   ::grpc::experimental::CallbackServerContext*
+    #endif
+                     context, const ::google::protobuf::Empty* request) { return this->StreamMetrics(context, request); }));
+    }
+    ~ExperimentalWithCallbackMethod_StreamMetrics() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status StreamMetrics(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::grpc::ServerWriter< ::dmi::Metric>* /*writer*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+    virtual ::grpc::ServerWriteReactor< ::dmi::Metric>* StreamMetrics(
+      ::grpc::CallbackServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/)
+    #else
+    virtual ::grpc::experimental::ServerWriteReactor< ::dmi::Metric>* StreamMetrics(
+      ::grpc::experimental::CallbackServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/)
+    #endif
+      { return nullptr; }
+  };
   #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
-  typedef ExperimentalWithCallbackMethod_ListMetrics<ExperimentalWithCallbackMethod_UpdateMetricsConfiguration<ExperimentalWithCallbackMethod_GetMetric<Service > > > CallbackService;
+  typedef ExperimentalWithCallbackMethod_ListMetrics<ExperimentalWithCallbackMethod_UpdateMetricsConfiguration<ExperimentalWithCallbackMethod_GetMetric<ExperimentalWithCallbackMethod_StreamMetrics<Service > > > > CallbackService;
   #endif
 
-  typedef ExperimentalWithCallbackMethod_ListMetrics<ExperimentalWithCallbackMethod_UpdateMetricsConfiguration<ExperimentalWithCallbackMethod_GetMetric<Service > > > ExperimentalCallbackService;
+  typedef ExperimentalWithCallbackMethod_ListMetrics<ExperimentalWithCallbackMethod_UpdateMetricsConfiguration<ExperimentalWithCallbackMethod_GetMetric<ExperimentalWithCallbackMethod_StreamMetrics<Service > > > > ExperimentalCallbackService;
   template <class BaseClass>
   class WithGenericMethod_ListMetrics : public BaseClass {
    private:
@@ -492,6 +589,23 @@
     }
   };
   template <class BaseClass>
+  class WithGenericMethod_StreamMetrics : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithGenericMethod_StreamMetrics() {
+      ::grpc::Service::MarkMethodGeneric(3);
+    }
+    ~WithGenericMethod_StreamMetrics() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status StreamMetrics(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::grpc::ServerWriter< ::dmi::Metric>* /*writer*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+  };
+  template <class BaseClass>
   class WithRawMethod_ListMetrics : public BaseClass {
    private:
     void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
@@ -552,6 +666,26 @@
     }
   };
   template <class BaseClass>
+  class WithRawMethod_StreamMetrics : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithRawMethod_StreamMetrics() {
+      ::grpc::Service::MarkMethodRaw(3);
+    }
+    ~WithRawMethod_StreamMetrics() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status StreamMetrics(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::grpc::ServerWriter< ::dmi::Metric>* /*writer*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    void RequestStreamMetrics(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncWriter< ::grpc::ByteBuffer>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
+      ::grpc::Service::RequestAsyncServerStreaming(3, context, request, writer, new_call_cq, notification_cq, tag);
+    }
+  };
+  template <class BaseClass>
   class ExperimentalWithRawCallbackMethod_ListMetrics : public BaseClass {
    private:
     void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
@@ -666,6 +800,44 @@
       { return nullptr; }
   };
   template <class BaseClass>
+  class ExperimentalWithRawCallbackMethod_StreamMetrics : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    ExperimentalWithRawCallbackMethod_StreamMetrics() {
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+      ::grpc::Service::
+    #else
+      ::grpc::Service::experimental().
+    #endif
+        MarkMethodRawCallback(3,
+          new ::grpc_impl::internal::CallbackServerStreamingHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>(
+            [this](
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+                   ::grpc::CallbackServerContext*
+    #else
+                   ::grpc::experimental::CallbackServerContext*
+    #endif
+                     context, const::grpc::ByteBuffer* request) { return this->StreamMetrics(context, request); }));
+    }
+    ~ExperimentalWithRawCallbackMethod_StreamMetrics() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable synchronous version of this method
+    ::grpc::Status StreamMetrics(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::grpc::ServerWriter< ::dmi::Metric>* /*writer*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
+    virtual ::grpc::ServerWriteReactor< ::grpc::ByteBuffer>* StreamMetrics(
+      ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/)
+    #else
+    virtual ::grpc::experimental::ServerWriteReactor< ::grpc::ByteBuffer>* StreamMetrics(
+      ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/)
+    #endif
+      { return nullptr; }
+  };
+  template <class BaseClass>
   class WithStreamedUnaryMethod_ListMetrics : public BaseClass {
    private:
     void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
@@ -747,8 +919,35 @@
     virtual ::grpc::Status StreamedGetMetric(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::dmi::GetMetricRequest,::dmi::GetMetricResponse>* server_unary_streamer) = 0;
   };
   typedef WithStreamedUnaryMethod_ListMetrics<WithStreamedUnaryMethod_UpdateMetricsConfiguration<WithStreamedUnaryMethod_GetMetric<Service > > > StreamedUnaryService;
-  typedef Service SplitStreamedService;
-  typedef WithStreamedUnaryMethod_ListMetrics<WithStreamedUnaryMethod_UpdateMetricsConfiguration<WithStreamedUnaryMethod_GetMetric<Service > > > StreamedService;
+  template <class BaseClass>
+  class WithSplitStreamingMethod_StreamMetrics : public BaseClass {
+   private:
+    void BaseClassMustBeDerivedFromService(const Service* /*service*/) {}
+   public:
+    WithSplitStreamingMethod_StreamMetrics() {
+      ::grpc::Service::MarkMethodStreamed(3,
+        new ::grpc::internal::SplitServerStreamingHandler<
+          ::google::protobuf::Empty, ::dmi::Metric>(
+            [this](::grpc_impl::ServerContext* context,
+                   ::grpc_impl::ServerSplitStreamer<
+                     ::google::protobuf::Empty, ::dmi::Metric>* streamer) {
+                       return this->StreamedStreamMetrics(context,
+                         streamer);
+                  }));
+    }
+    ~WithSplitStreamingMethod_StreamMetrics() override {
+      BaseClassMustBeDerivedFromService(this);
+    }
+    // disable regular version of this method
+    ::grpc::Status StreamMetrics(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::grpc::ServerWriter< ::dmi::Metric>* /*writer*/) override {
+      abort();
+      return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
+    }
+    // replace default version of method with split streamed
+    virtual ::grpc::Status StreamedStreamMetrics(::grpc::ServerContext* context, ::grpc::ServerSplitStreamer< ::google::protobuf::Empty,::dmi::Metric>* server_split_streamer) = 0;
+  };
+  typedef WithSplitStreamingMethod_StreamMetrics<Service > SplitStreamedService;
+  typedef WithStreamedUnaryMethod_ListMetrics<WithStreamedUnaryMethod_UpdateMetricsConfiguration<WithStreamedUnaryMethod_GetMetric<WithSplitStreamingMethod_StreamMetrics<Service > > > > StreamedService;
 };
 
 }  // namespace dmi
diff --git a/cpp/dmi/hw_metrics_mgmt_service.pb.cc b/cpp/dmi/hw_metrics_mgmt_service.pb.cc
index 389e53d..14a0306 100644
--- a/cpp/dmi/hw_metrics_mgmt_service.pb.cc
+++ b/cpp/dmi/hw_metrics_mgmt_service.pb.cc
@@ -319,85 +319,88 @@
 
 const char descriptor_table_protodef_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[] =
   "\n!dmi/hw_metrics_mgmt_service.proto\022\003dmi"
-  "\032\021dmi/commons.proto\032\014dmi/hw.proto\"a\n\014Met"
-  "ricConfig\022#\n\tmetric_id\030\001 \001(\0162\020.dmi.Metri"
-  "cNames\022\025\n\ris_configured\030\002 \001(\010\022\025\n\rpoll_in"
-  "terval\030\003 \001(\r\"3\n\rMetricsConfig\022\"\n\007metrics"
-  "\030\001 \003(\0132\021.dmi.MetricConfig\"\377\001\n\023ListMetric"
-  "sResponse\022\033\n\006status\030\001 \001(\0162\013.dmi.Status\022/"
-  "\n\006reason\030\002 \001(\0162\037.dmi.ListMetricsResponse"
-  ".Reason\022#\n\007metrics\030\003 \001(\0132\022.dmi.MetricsCo"
-  "nfig\022\025\n\rreason_detail\030\004 \001(\t\"^\n\006Reason\022\024\n"
-  "\020UNDEFINED_REASON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022"
-  "\022\n\016INTERNAL_ERROR\020\002\022\026\n\022DEVICE_UNREACHABL"
-  "E\020\003\"\215\001\n\033MetricsConfigurationRequest\022\036\n\013d"
-  "evice_uuid\030\001 \001(\0132\t.dmi.Uuid\022%\n\007changes\030\002"
-  " \001(\0132\022.dmi.MetricsConfigH\000\022\032\n\020reset_to_d"
-  "efault\030\003 \001(\010H\000B\013\n\toperation\"\240\002\n\034MetricsC"
-  "onfigurationResponse\022\033\n\006status\030\001 \001(\0162\013.d"
-  "mi.Status\0228\n\006reason\030\002 \001(\0162(.dmi.MetricsC"
-  "onfigurationResponse.Reason\022\025\n\rreason_de"
-  "tail\030\003 \001(\t\"\221\001\n\006Reason\022\024\n\020UNDEFINED_REASO"
-  "N\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERNAL_ERRO"
-  "R\020\002\022\035\n\031POLL_INTERVAL_UNSUPPORTED\020\003\022\022\n\016IN"
-  "VALID_METRIC\020\004\022\026\n\022DEVICE_UNREACHABLE\020\005\"k"
-  "\n\016MetricMetaData\022\036\n\013device_uuid\030\001 \001(\0132\t."
-  "dmi.Uuid\022!\n\016component_uuid\030\002 \001(\0132\t.dmi.U"
-  "uid\022\026\n\016component_name\030\003 \001(\t\"\204\001\n\006Metric\022#"
-  "\n\tmetric_id\030\001 \001(\0162\020.dmi.MetricNames\022,\n\017m"
-  "etric_metadata\030\002 \001(\0132\023.dmi.MetricMetaDat"
-  "a\022\'\n\005value\030\003 \001(\0132\030.dmi.ComponentSensorDa"
-  "ta\"_\n\020GetMetricRequest\022&\n\tmeta_data\030\001 \001("
-  "\0132\023.dmi.MetricMetaData\022#\n\tmetric_id\030\002 \001("
-  "\0162\020.dmi.MetricNames\"\237\002\n\021GetMetricRespons"
-  "e\022\033\n\006status\030\001 \001(\0162\013.dmi.Status\022-\n\006reason"
-  "\030\002 \001(\0162\035.dmi.GetMetricResponse.Reason\022\033\n"
-  "\006metric\030\003 \001(\0132\013.dmi.Metric\022\025\n\rreason_det"
-  "ail\030\004 \001(\t\"\211\001\n\006Reason\022\024\n\020UNDEFINED_REASON"
-  "\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\025\n\021UNKNOWN_COMPON"
-  "ENT\020\002\022\022\n\016INTERNAL_ERROR\020\003\022\022\n\016INVALID_MET"
-  "RIC\020\004\022\026\n\022DEVICE_UNREACHABLE\020\005*\331\005\n\013Metric"
-  "Names\022\031\n\025METRIC_NAME_UNDEFINED\020\000\022\024\n\020METR"
-  "IC_FAN_SPEED\020\001\022\023\n\017METRIC_CPU_TEMP\020d\022\037\n\033M"
-  "ETRIC_CPU_USAGE_PERCENTAGE\020e\022\034\n\027METRIC_T"
-  "RANSCEIVER_TEMP\020\310\001\022\037\n\032METRIC_TRANSCEIVER"
-  "_VOLTAGE\020\311\001\022\034\n\027METRIC_TRANSCEIVER_BIAS\020\312"
-  "\001\022 \n\033METRIC_TRANSCEIVER_RX_POWER\020\313\001\022 \n\033M"
-  "ETRIC_TRANSCEIVER_TX_POWER\020\314\001\022\"\n\035METRIC_"
-  "TRANSCEIVER_WAVELENGTH\020\315\001\022\025\n\020METRIC_DISK"
-  "_TEMP\020\254\002\022\031\n\024METRIC_DISK_CAPACITY\020\255\002\022\026\n\021M"
-  "ETRIC_DISK_USAGE\020\256\002\022!\n\034METRIC_DISK_USAGE"
-  "_PERCENTAGE\020\257\002\022&\n!METRIC_DISK_READ_WRITE"
-  "_PERCENTAGE\020\260\002\022(\n#METRIC_DISK_FAULTY_CEL"
-  "LS_PERCENTAGE\020\261\002\022\024\n\017METRIC_RAM_TEMP\020\220\003\022\030"
-  "\n\023METRIC_RAM_CAPACITY\020\221\003\022\025\n\020METRIC_RAM_U"
-  "SAGE\020\222\003\022 \n\033METRIC_RAM_USAGE_PERCENTAGE\020\223"
-  "\003\022\025\n\020METRIC_POWER_MAX\020\364\003\022\027\n\022METRIC_POWER"
-  "_USAGE\020\365\003\022\"\n\035METRIC_POWER_USAGE_PERCENTA"
-  "GE\020\366\003\022\"\n\035METRIC_INNER_SURROUNDING_TEMP\020\330"
-  "\0042\371\001\n\036NativeMetricsManagementService\0228\n\013"
-  "ListMetrics\022\017.dmi.HardwareID\032\030.dmi.ListM"
-  "etricsResponse\022a\n\032UpdateMetricsConfigura"
-  "tion\022 .dmi.MetricsConfigurationRequest\032!"
-  ".dmi.MetricsConfigurationResponse\022:\n\tGet"
-  "Metric\022\025.dmi.GetMetricRequest\032\026.dmi.GetM"
-  "etricResponseB;Z9github.com/opencord/dev"
-  "ice-management-interface/v3/go/dmib\006prot"
-  "o3"
+  "\032\021dmi/commons.proto\032\014dmi/hw.proto\032\033googl"
+  "e/protobuf/empty.proto\"a\n\014MetricConfig\022#"
+  "\n\tmetric_id\030\001 \001(\0162\020.dmi.MetricNames\022\025\n\ri"
+  "s_configured\030\002 \001(\010\022\025\n\rpoll_interval\030\003 \001("
+  "\r\"3\n\rMetricsConfig\022\"\n\007metrics\030\001 \003(\0132\021.dm"
+  "i.MetricConfig\"\377\001\n\023ListMetricsResponse\022\033"
+  "\n\006status\030\001 \001(\0162\013.dmi.Status\022/\n\006reason\030\002 "
+  "\001(\0162\037.dmi.ListMetricsResponse.Reason\022#\n\007"
+  "metrics\030\003 \001(\0132\022.dmi.MetricsConfig\022\025\n\rrea"
+  "son_detail\030\004 \001(\t\"^\n\006Reason\022\024\n\020UNDEFINED_"
+  "REASON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERNAL"
+  "_ERROR\020\002\022\026\n\022DEVICE_UNREACHABLE\020\003\"\215\001\n\033Met"
+  "ricsConfigurationRequest\022\036\n\013device_uuid\030"
+  "\001 \001(\0132\t.dmi.Uuid\022%\n\007changes\030\002 \001(\0132\022.dmi."
+  "MetricsConfigH\000\022\032\n\020reset_to_default\030\003 \001("
+  "\010H\000B\013\n\toperation\"\240\002\n\034MetricsConfiguratio"
+  "nResponse\022\033\n\006status\030\001 \001(\0162\013.dmi.Status\0228"
+  "\n\006reason\030\002 \001(\0162(.dmi.MetricsConfiguratio"
+  "nResponse.Reason\022\025\n\rreason_detail\030\003 \001(\t\""
+  "\221\001\n\006Reason\022\024\n\020UNDEFINED_REASON\020\000\022\022\n\016UNKN"
+  "OWN_DEVICE\020\001\022\022\n\016INTERNAL_ERROR\020\002\022\035\n\031POLL"
+  "_INTERVAL_UNSUPPORTED\020\003\022\022\n\016INVALID_METRI"
+  "C\020\004\022\026\n\022DEVICE_UNREACHABLE\020\005\"k\n\016MetricMet"
+  "aData\022\036\n\013device_uuid\030\001 \001(\0132\t.dmi.Uuid\022!\n"
+  "\016component_uuid\030\002 \001(\0132\t.dmi.Uuid\022\026\n\016comp"
+  "onent_name\030\003 \001(\t\"\204\001\n\006Metric\022#\n\tmetric_id"
+  "\030\001 \001(\0162\020.dmi.MetricNames\022,\n\017metric_metad"
+  "ata\030\002 \001(\0132\023.dmi.MetricMetaData\022\'\n\005value\030"
+  "\003 \001(\0132\030.dmi.ComponentSensorData\"_\n\020GetMe"
+  "tricRequest\022&\n\tmeta_data\030\001 \001(\0132\023.dmi.Met"
+  "ricMetaData\022#\n\tmetric_id\030\002 \001(\0162\020.dmi.Met"
+  "ricNames\"\237\002\n\021GetMetricResponse\022\033\n\006status"
+  "\030\001 \001(\0162\013.dmi.Status\022-\n\006reason\030\002 \001(\0162\035.dm"
+  "i.GetMetricResponse.Reason\022\033\n\006metric\030\003 \001"
+  "(\0132\013.dmi.Metric\022\025\n\rreason_detail\030\004 \001(\t\"\211"
+  "\001\n\006Reason\022\024\n\020UNDEFINED_REASON\020\000\022\022\n\016UNKNO"
+  "WN_DEVICE\020\001\022\025\n\021UNKNOWN_COMPONENT\020\002\022\022\n\016IN"
+  "TERNAL_ERROR\020\003\022\022\n\016INVALID_METRIC\020\004\022\026\n\022DE"
+  "VICE_UNREACHABLE\020\005*\331\005\n\013MetricNames\022\031\n\025ME"
+  "TRIC_NAME_UNDEFINED\020\000\022\024\n\020METRIC_FAN_SPEE"
+  "D\020\001\022\023\n\017METRIC_CPU_TEMP\020d\022\037\n\033METRIC_CPU_U"
+  "SAGE_PERCENTAGE\020e\022\034\n\027METRIC_TRANSCEIVER_"
+  "TEMP\020\310\001\022\037\n\032METRIC_TRANSCEIVER_VOLTAGE\020\311\001"
+  "\022\034\n\027METRIC_TRANSCEIVER_BIAS\020\312\001\022 \n\033METRIC"
+  "_TRANSCEIVER_RX_POWER\020\313\001\022 \n\033METRIC_TRANS"
+  "CEIVER_TX_POWER\020\314\001\022\"\n\035METRIC_TRANSCEIVER"
+  "_WAVELENGTH\020\315\001\022\025\n\020METRIC_DISK_TEMP\020\254\002\022\031\n"
+  "\024METRIC_DISK_CAPACITY\020\255\002\022\026\n\021METRIC_DISK_"
+  "USAGE\020\256\002\022!\n\034METRIC_DISK_USAGE_PERCENTAGE"
+  "\020\257\002\022&\n!METRIC_DISK_READ_WRITE_PERCENTAGE"
+  "\020\260\002\022(\n#METRIC_DISK_FAULTY_CELLS_PERCENTA"
+  "GE\020\261\002\022\024\n\017METRIC_RAM_TEMP\020\220\003\022\030\n\023METRIC_RA"
+  "M_CAPACITY\020\221\003\022\025\n\020METRIC_RAM_USAGE\020\222\003\022 \n\033"
+  "METRIC_RAM_USAGE_PERCENTAGE\020\223\003\022\025\n\020METRIC"
+  "_POWER_MAX\020\364\003\022\027\n\022METRIC_POWER_USAGE\020\365\003\022\""
+  "\n\035METRIC_POWER_USAGE_PERCENTAGE\020\366\003\022\"\n\035ME"
+  "TRIC_INNER_SURROUNDING_TEMP\020\330\0042\261\002\n\036Nativ"
+  "eMetricsManagementService\0228\n\013ListMetrics"
+  "\022\017.dmi.HardwareID\032\030.dmi.ListMetricsRespo"
+  "nse\022a\n\032UpdateMetricsConfiguration\022 .dmi."
+  "MetricsConfigurationRequest\032!.dmi.Metric"
+  "sConfigurationResponse\022:\n\tGetMetric\022\025.dm"
+  "i.GetMetricRequest\032\026.dmi.GetMetricRespon"
+  "se\0226\n\rStreamMetrics\022\026.google.protobuf.Em"
+  "pty\032\013.dmi.Metric0\001B;Z9github.com/opencor"
+  "d/device-management-interface/v3/go/dmib"
+  "\006proto3"
   ;
 ::google::protobuf::internal::DescriptorTable descriptor_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = {
   false, InitDefaults_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, 
   descriptor_table_protodef_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto,
-  "dmi/hw_metrics_mgmt_service.proto", &assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, 2602,
+  "dmi/hw_metrics_mgmt_service.proto", &assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, 2687,
 };
 
 void AddDescriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
-  static constexpr ::google::protobuf::internal::InitFunc deps[2] =
+  static constexpr ::google::protobuf::internal::InitFunc deps[3] =
   {
     ::AddDescriptors_dmi_2fcommons_2eproto,
     ::AddDescriptors_dmi_2fhw_2eproto,
+    ::AddDescriptors_google_2fprotobuf_2fempty_2eproto,
   };
- ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, deps, 2);
+ ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, deps, 3);
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
diff --git a/cpp/dmi/hw_metrics_mgmt_service.pb.h b/cpp/dmi/hw_metrics_mgmt_service.pb.h
index 5967faa..ab393ae 100644
--- a/cpp/dmi/hw_metrics_mgmt_service.pb.h
+++ b/cpp/dmi/hw_metrics_mgmt_service.pb.h
@@ -34,6 +34,7 @@
 #include <google/protobuf/unknown_field_set.h>
 #include "dmi/commons.pb.h"
 #include "dmi/hw.pb.h"
+#include <google/protobuf/empty.pb.h>
 // @@protoc_insertion_point(includes)
 #include <google/protobuf/port_def.inc>
 #define PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto