Merge "[VOL-3695]: Support to create some of the OLT device events over the Device Management Interface     1. Following events and its corresponding recovered event creation is supported :        EVENT_FAN_FAILURE        EVENT_PSU_FAILURE        EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL     2. Following DMI Native Events Management Service APIs are implemented:        ListEvents        UpdateEventsConfiguration     3. Updated docs/source/DMI_Server_README.md"
diff --git a/Makefile b/Makefile
index 3ffc3a9..481a9ff 100644
--- a/Makefile
+++ b/Makefile
@@ -39,7 +39,7 @@
 # Public targets
 all: help
 
-protos: api/bbsim/bbsim.pb.go api/bbsim/bbsim.pb.gw.go api/legacy/bbsim.pb.go api/legacy/bbsim.pb.gw.go # @HELP Build proto files
+protos: api/bbsim/bbsim.pb.go api/bbsim/bbsim.pb.gw.go api/legacy/bbsim.pb.go api/legacy/bbsim.pb.gw.go api/bbsim/bbsim_dmi.pb.go # @HELP Build proto files
 
 .PHONY: build
 build: protos build-bbsim build-bbsimctl build-bbr
@@ -244,6 +244,13 @@
       --go_out=plugins=grpc:./ \
       $<
 
+api/bbsim/bbsim_dmi.pb.go: api/bbsim/bbsim_dmi.proto setup_tools
+	@echo $@
+	@${PROTOC} -I. \
+      -I${GOOGLEAPI}/third_party/googleapis \
+      --go_out=plugins=grpc:./ \
+      $<
+
 api/bbsim/bbsim.pb.go api/bbsim/bbsim.pb.gw.go: api/bbsim/bbsim.proto api/bbsim/bbsim.yaml setup_tools
 	@echo $@
 	@${PROTOC} -I. \
diff --git a/api/bbsim/bbsim.pb.go b/api/bbsim/bbsim.pb.go
index ffa0154..a4b6f11 100644
--- a/api/bbsim/bbsim.pb.go
+++ b/api/bbsim/bbsim.pb.go
@@ -1419,7 +1419,7 @@
 	StopgRPCServer(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Response, error)
 	// Start the Openolt gRPC server
 	StartgRPCServer(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Response, error)
-	// Start the Openolt gRPC server
+	// Restart the Openolt gRPC server after the given timeout
 	RestartgRPCServer(ctx context.Context, in *Timeout, opts ...grpc.CallOption) (*Response, error)
 	// Get status of an ONU by serial number
 	GetONU(ctx context.Context, in *ONURequest, opts ...grpc.CallOption) (*ONU, error)
@@ -1717,7 +1717,7 @@
 	StopgRPCServer(context.Context, *Empty) (*Response, error)
 	// Start the Openolt gRPC server
 	StartgRPCServer(context.Context, *Empty) (*Response, error)
-	// Start the Openolt gRPC server
+	// Restart the Openolt gRPC server after the given timeout
 	RestartgRPCServer(context.Context, *Timeout) (*Response, error)
 	// Get status of an ONU by serial number
 	GetONU(context.Context, *ONURequest) (*ONU, error)
diff --git a/api/bbsim/bbsim_dmi.pb.go b/api/bbsim/bbsim_dmi.pb.go
new file mode 100644
index 0000000..7dd373d
--- /dev/null
+++ b/api/bbsim/bbsim_dmi.pb.go
@@ -0,0 +1,216 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: api/bbsim/bbsim_dmi.proto
+
+package bbsim
+
+import (
+	context "context"
+	fmt "fmt"
+	proto "github.com/golang/protobuf/proto"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+type DmiEvent struct {
+	EventName            string   `protobuf:"bytes,1,opt,name=event_name,json=eventName,proto3" json:"event_name,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *DmiEvent) Reset()         { *m = DmiEvent{} }
+func (m *DmiEvent) String() string { return proto.CompactTextString(m) }
+func (*DmiEvent) ProtoMessage()    {}
+func (*DmiEvent) Descriptor() ([]byte, []int) {
+	return fileDescriptor_49e784b4938902cc, []int{0}
+}
+
+func (m *DmiEvent) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_DmiEvent.Unmarshal(m, b)
+}
+func (m *DmiEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_DmiEvent.Marshal(b, m, deterministic)
+}
+func (m *DmiEvent) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DmiEvent.Merge(m, src)
+}
+func (m *DmiEvent) XXX_Size() int {
+	return xxx_messageInfo_DmiEvent.Size(m)
+}
+func (m *DmiEvent) XXX_DiscardUnknown() {
+	xxx_messageInfo_DmiEvent.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DmiEvent proto.InternalMessageInfo
+
+func (m *DmiEvent) GetEventName() string {
+	if m != nil {
+		return m.EventName
+	}
+	return ""
+}
+
+type DmiCreateEventResponse struct {
+	StatusCode           int32    `protobuf:"varint,1,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"`
+	Message              string   `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
+	XXX_NoUnkeyedLiteral struct{} `json:"-"`
+	XXX_unrecognized     []byte   `json:"-"`
+	XXX_sizecache        int32    `json:"-"`
+}
+
+func (m *DmiCreateEventResponse) Reset()         { *m = DmiCreateEventResponse{} }
+func (m *DmiCreateEventResponse) String() string { return proto.CompactTextString(m) }
+func (*DmiCreateEventResponse) ProtoMessage()    {}
+func (*DmiCreateEventResponse) Descriptor() ([]byte, []int) {
+	return fileDescriptor_49e784b4938902cc, []int{1}
+}
+
+func (m *DmiCreateEventResponse) XXX_Unmarshal(b []byte) error {
+	return xxx_messageInfo_DmiCreateEventResponse.Unmarshal(m, b)
+}
+func (m *DmiCreateEventResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+	return xxx_messageInfo_DmiCreateEventResponse.Marshal(b, m, deterministic)
+}
+func (m *DmiCreateEventResponse) XXX_Merge(src proto.Message) {
+	xxx_messageInfo_DmiCreateEventResponse.Merge(m, src)
+}
+func (m *DmiCreateEventResponse) XXX_Size() int {
+	return xxx_messageInfo_DmiCreateEventResponse.Size(m)
+}
+func (m *DmiCreateEventResponse) XXX_DiscardUnknown() {
+	xxx_messageInfo_DmiCreateEventResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DmiCreateEventResponse proto.InternalMessageInfo
+
+func (m *DmiCreateEventResponse) GetStatusCode() int32 {
+	if m != nil {
+		return m.StatusCode
+	}
+	return 0
+}
+
+func (m *DmiCreateEventResponse) GetMessage() string {
+	if m != nil {
+		return m.Message
+	}
+	return ""
+}
+
+func init() {
+	proto.RegisterType((*DmiEvent)(nil), "bbsim.DmiEvent")
+	proto.RegisterType((*DmiCreateEventResponse)(nil), "bbsim.DmiCreateEventResponse")
+}
+
+func init() { proto.RegisterFile("api/bbsim/bbsim_dmi.proto", fileDescriptor_49e784b4938902cc) }
+
+var fileDescriptor_49e784b4938902cc = []byte{
+	// 190 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0x2c, 0xc8, 0xd4,
+	0x4f, 0x4a, 0x2a, 0xce, 0xcc, 0x85, 0x90, 0xf1, 0x29, 0xb9, 0x99, 0x7a, 0x05, 0x45, 0xf9, 0x25,
+	0xf9, 0x42, 0xac, 0x60, 0x01, 0x25, 0x4d, 0x2e, 0x0e, 0x97, 0xdc, 0x4c, 0xd7, 0xb2, 0xd4, 0xbc,
+	0x12, 0x21, 0x59, 0x2e, 0xae, 0x54, 0x10, 0x23, 0x3e, 0x2f, 0x31, 0x37, 0x55, 0x82, 0x51, 0x81,
+	0x51, 0x83, 0x33, 0x88, 0x13, 0x2c, 0xe2, 0x97, 0x98, 0x9b, 0xaa, 0x14, 0xcc, 0x25, 0xe6, 0x92,
+	0x9b, 0xe9, 0x5c, 0x94, 0x9a, 0x58, 0x92, 0x0a, 0xd6, 0x10, 0x94, 0x5a, 0x5c, 0x90, 0x9f, 0x57,
+	0x9c, 0x2a, 0x24, 0xcf, 0xc5, 0x5d, 0x5c, 0x92, 0x58, 0x52, 0x5a, 0x1c, 0x9f, 0x9c, 0x9f, 0x02,
+	0xd1, 0xc9, 0x1a, 0xc4, 0x05, 0x11, 0x72, 0xce, 0x4f, 0x49, 0x15, 0x92, 0xe0, 0x62, 0xcf, 0x4d,
+	0x2d, 0x2e, 0x4e, 0x4c, 0x4f, 0x95, 0x60, 0x02, 0x1b, 0x0b, 0xe3, 0x1a, 0xf9, 0x70, 0x71, 0x3a,
+	0x39, 0x41, 0x5d, 0x26, 0x64, 0xcf, 0xc5, 0x8d, 0x64, 0xbc, 0x10, 0xbf, 0x1e, 0xd8, 0x8d, 0x7a,
+	0x30, 0x07, 0x4a, 0xc9, 0x22, 0x04, 0xb0, 0x38, 0x43, 0x89, 0x21, 0x89, 0x0d, 0xec, 0x37, 0x63,
+	0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x8b, 0xf2, 0xfd, 0xf8, 0x00, 0x00, 0x00,
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// BBsimDmiClient is the client API for BBsimDmi service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type BBsimDmiClient interface {
+	// Ask the DMI Server to create an event
+	CreateEvent(ctx context.Context, in *DmiEvent, opts ...grpc.CallOption) (*DmiCreateEventResponse, error)
+}
+
+type bBsimDmiClient struct {
+	cc *grpc.ClientConn
+}
+
+func NewBBsimDmiClient(cc *grpc.ClientConn) BBsimDmiClient {
+	return &bBsimDmiClient{cc}
+}
+
+func (c *bBsimDmiClient) CreateEvent(ctx context.Context, in *DmiEvent, opts ...grpc.CallOption) (*DmiCreateEventResponse, error) {
+	out := new(DmiCreateEventResponse)
+	err := c.cc.Invoke(ctx, "/bbsim.BBsim_dmi/CreateEvent", in, out, opts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// BBsimDmiServer is the server API for BBsimDmi service.
+type BBsimDmiServer interface {
+	// Ask the DMI Server to create an event
+	CreateEvent(context.Context, *DmiEvent) (*DmiCreateEventResponse, error)
+}
+
+// UnimplementedBBsimDmiServer can be embedded to have forward compatible implementations.
+type UnimplementedBBsimDmiServer struct {
+}
+
+func (*UnimplementedBBsimDmiServer) CreateEvent(ctx context.Context, req *DmiEvent) (*DmiCreateEventResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method CreateEvent not implemented")
+}
+
+func RegisterBBsimDmiServer(s *grpc.Server, srv BBsimDmiServer) {
+	s.RegisterService(&_BBsimDmi_serviceDesc, srv)
+}
+
+func _BBsimDmi_CreateEvent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(DmiEvent)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(BBsimDmiServer).CreateEvent(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: "/bbsim.BBsim_dmi/CreateEvent",
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(BBsimDmiServer).CreateEvent(ctx, req.(*DmiEvent))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+var _BBsimDmi_serviceDesc = grpc.ServiceDesc{
+	ServiceName: "bbsim.BBsim_dmi",
+	HandlerType: (*BBsimDmiServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "CreateEvent",
+			Handler:    _BBsimDmi_CreateEvent_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "api/bbsim/bbsim_dmi.proto",
+}
diff --git a/api/bbsim/bbsim_dmi.proto b/api/bbsim/bbsim_dmi.proto
new file mode 100644
index 0000000..c560598
--- /dev/null
+++ b/api/bbsim/bbsim_dmi.proto
@@ -0,0 +1,32 @@
+// Copyright (c) 2018 Open Networking Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+package bbsim;
+
+
+message DmiEvent {
+   string event_name= 1;
+}
+
+message DmiCreateEventResponse {
+    int32 status_code = 1;
+    string message = 2;
+}
+
+service BBsim_dmi {
+    // Ask the DMI Server to create an event
+    rpc CreateEvent (DmiEvent) returns (DmiCreateEventResponse){
+    }
+}
diff --git a/cmd/bbsimctl/bbsimctl.go b/cmd/bbsimctl/bbsimctl.go
index 08e7b5b..293c164 100644
--- a/cmd/bbsimctl/bbsimctl.go
+++ b/cmd/bbsimctl/bbsimctl.go
@@ -42,6 +42,7 @@
 	commands.RegisterPonCommands(parser)
 	commands.RegisterCompletionCommands(parser)
 	commands.RegisterLoggingCommands(parser)
+	commands.RegisterDMICommands(parser)
 
 	_, err = parser.ParseArgs(os.Args[1:])
 	if err != nil {
diff --git a/docs/source/DMI_Server_README.md b/docs/source/DMI_Server_README.md
index 1f3e660..229bb82 100755
--- a/docs/source/DMI_Server_README.md
+++ b/docs/source/DMI_Server_README.md
@@ -276,4 +276,105 @@
     ]
   }
 }
+```
+### List NativeEventsManagementService APIs
+``` sh
+$ grpcurl -plaintext 172.17.0.2:50075 list dmi.NativeEventsManagementService
+dmi.NativeEventsManagementService.ListEvents
+dmi.NativeEventsManagementService.UpdateEventsConfiguration
+```
+### ListEvents API
+``` sh
+$ grpcurl -plaintext -d '{"uuid": {"uuid":"5295a1d5-a121-372e-b8dc-6f7eda83f0ba"}}' 172.17.0.2:50075 dmi.NativeEventsManagementService.ListEvents
+{
+  "status": "OK_STATUS",
+  "events": {
+    "items": [
+      {
+        "eventId": "EVENT_FAN_FAILURE",
+        "isConfigured": true
+      },
+      {
+        "eventId": "EVENT_CPU_TEMPERATURE_ABOVE_CRITICAL",
+        "isConfigured": true,
+        "thresholds": {
+          "upper": {
+            "high": {
+              "intVal": "95"
+            },
+            "low": {
+              "intVal": "90"
+            }
+          }
+        }
+      },
+      {
+        "eventId": "EVENT_PSU_FAILURE",
+        "isConfigured": true
+      }
+    ]
+  }
+}
+
+```
+
+### UpdateEventsConfiguration API
+For FAN Failure, event_id must be set to 300 in grpc curl since enum value is 300
+Please refer enums values corresponding to events in
+https://github.com/opencord/device-management-interface/blob/master/protos/dmi/hw_events_mgmt_service.proto
+``` sh
+$ grpcurl -plaintext -d '{"device_uuid": {"uuid":"5295a1d5-a121-372e-b8dc-6f7eda83f0ba"}, "changes": {"items":{"event_id":"300", "is_configured": "false"}}}' 172.17.0.2:50075 dmi.NativeEventsManagementService.UpdateEventsConfiguration
+{
+  "status": "OK_STATUS"
+}
+```
+## Generate DMI Events
+Access bbsimctl
++++++++++++++++
+
+When running a test you can check the state of each ONU using ``BBSimCtl``.
+
+The easiest way to use ``bbsimctl`` is to ``exec`` inside the ``bbsim`` container:
+
+.. code:: bash
+
+    kubectl -n voltha exec -it $(kubectl -n voltha get pods -l app=bbsim -o name) -- /bin/bash
+
+In case you prefer to run ``bbsimctl`` on your machine,
+it can be configured via a config file such as:
+
+.. code:: bash
+
+    $ cat ~/.bbsim/config
+    apiVersion: v1
+    server: 127.0.0.1:50070
+    grpc:
+      timeout: 10s
+
+Note : For event names, refer EventIds enum in https://github.com/opencord/device-management-interface/blob/master/protos/dmi/hw_events_mgmt_service.proto .
+
+$ bsimctl dmi events raise <event_name>
+
+###  FAN FAILURE EVENT
+
+.. code:: bash
+```
+$ bsimctl dmi events create EVENT_FAN_FAILURE
+[Status: 0] DMI Event Indication Sent.
+```
+
+###  PSU FAILURE EVENT
+
+.. code:: bash
+```
+$ bsimctl dmi events create EVENT_PSU_FAILURE
+[Status: 0] DMI Event Indication Sent.
+```
+
+###  HW DEVICE TEMPERATURE ABOVE CRITICAL EVENT
+
+.. code:: bash
+```
+$ bsimctl dmi events create EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL
+[Status: 0] DMI Event Indication Sent.
 ```
\ No newline at end of file
diff --git a/internal/bbsim/dmiserver/dmi_api_server.go b/internal/bbsim/dmiserver/dmi_api_server.go
index f64f801..272f3c9 100755
--- a/internal/bbsim/dmiserver/dmi_api_server.go
+++ b/internal/bbsim/dmiserver/dmi_api_server.go
@@ -20,6 +20,7 @@
 	"context"
 	"net"
 
+	"github.com/opencord/bbsim/api/bbsim"
 	"github.com/opencord/bbsim/internal/common"
 	dmi "github.com/opencord/device-management-interface/go/dmi"
 	log "github.com/sirupsen/logrus"
@@ -42,6 +43,7 @@
 	ponTransceiverCageUuids []string
 	root                    *dmi.Component
 	metricChannel           chan interface{}
+	eventChannel            chan interface{}
 	kafkaEndpoint           string
 	mPublisherCancelFunc    context.CancelFunc
 }
@@ -69,6 +71,7 @@
 	dmi.RegisterNativeSoftwareManagementServiceServer(grpcServer, dms)
 	dmi.RegisterNativeEventsManagementServiceServer(grpcServer, dms)
 	dmi.RegisterNativeMetricsManagementServiceServer(grpcServer, dms)
+	bbsim.RegisterBBsimDmiServer(grpcServer, dms)
 
 	reflection.Register(grpcServer)
 
diff --git a/internal/bbsim/dmiserver/dmi_event_generator.go b/internal/bbsim/dmiserver/dmi_event_generator.go
new file mode 100644
index 0000000..b25cb59
--- /dev/null
+++ b/internal/bbsim/dmiserver/dmi_event_generator.go
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dmiserver
+
+import (
+	"context"
+	"fmt"
+	"sync"
+
+	"github.com/golang/protobuf/ptypes"
+	"github.com/opencord/bbsim/api/bbsim"
+	"github.com/opencord/device-management-interface/go/dmi"
+	log "github.com/sirupsen/logrus"
+	"google.golang.org/grpc/codes"
+)
+
+//DmiEventsGenerator has the attributes for generating events
+type DmiEventsGenerator struct {
+	apiSrv           *DmiAPIServer
+	configuredEvents map[dmi.EventIds]dmi.EventCfg
+	access           sync.Mutex
+}
+
+// func to generate the different types of events, there are two types one with thresholds and one without
+type eventGenerationFunc func(dmi.EventIds, dmi.ComponentType)
+
+// eventGenerationUtil contains the component and the func for a specific eventId
+type eventGenerationUtil struct {
+	componentType dmi.ComponentType
+	genFunc       eventGenerationFunc
+}
+
+var dmiEG DmiEventsGenerator
+var eventGenMap map[dmi.EventIds]eventGenerationUtil
+
+func init() {
+	eventGenMap = make(map[dmi.EventIds]eventGenerationUtil)
+	eventGenMap[dmi.EventIds_EVENT_FAN_FAILURE] = eventGenerationUtil{
+		componentType: dmi.ComponentType_COMPONENT_TYPE_FAN,
+		genFunc:       noThresholdEventGenerationFunc,
+	}
+	eventGenMap[dmi.EventIds_EVENT_FAN_FAILURE_RECOVERED] = eventGenerationUtil{
+		componentType: dmi.ComponentType_COMPONENT_TYPE_FAN,
+		genFunc:       noThresholdEventGenerationFunc,
+	}
+
+	eventGenMap[dmi.EventIds_EVENT_PSU_FAILURE] = eventGenerationUtil{
+		componentType: dmi.ComponentType_COMPONENT_TYPE_POWER_SUPPLY,
+		genFunc:       noThresholdEventGenerationFunc,
+	}
+	eventGenMap[dmi.EventIds_EVENT_PSU_FAILURE_RECOVERED] = eventGenerationUtil{
+		componentType: dmi.ComponentType_COMPONENT_TYPE_POWER_SUPPLY,
+		genFunc:       noThresholdEventGenerationFunc,
+	}
+
+	eventGenMap[dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL] = eventGenerationUtil{
+		componentType: dmi.ComponentType_COMPONENT_TYPE_SENSOR,
+		genFunc:       thresholdEventGenerationFunc,
+	}
+	eventGenMap[dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL_RECOVERED] = eventGenerationUtil{
+		componentType: dmi.ComponentType_COMPONENT_TYPE_SENSOR,
+		genFunc:       thresholdEventGenerationFunc,
+	}
+}
+
+//StartEventsGenerator initializes the event generator
+func StartEventsGenerator(apiSrv *DmiAPIServer) {
+	log.Debugf("StartEventsGenerator invoked")
+
+	dmiEG = DmiEventsGenerator{
+		apiSrv: apiSrv,
+	}
+	dmiEG.configuredEvents = make(map[dmi.EventIds]dmi.EventCfg)
+
+	// Add Fan Failure event configuration
+	dmiEG.configuredEvents[dmi.EventIds_EVENT_FAN_FAILURE] = dmi.EventCfg{
+		EventId:      dmi.EventIds_EVENT_FAN_FAILURE,
+		IsConfigured: true,
+	}
+
+	// Add hardware device temp above critical event configuration
+	dmiEG.configuredEvents[dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL] = dmi.EventCfg{
+		EventId:      dmi.EventIds_EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL,
+		IsConfigured: true,
+		Thresholds: &dmi.Thresholds{
+			Threshold: &dmi.Thresholds_Upper{Upper: &dmi.WaterMarks{
+				High: &dmi.ValueType{
+					Val: &dmi.ValueType_IntVal{IntVal: 95},
+				},
+				Low: &dmi.ValueType{
+					Val: &dmi.ValueType_IntVal{IntVal: 90},
+				},
+			}},
+		},
+	}
+
+	// Add Power Supply Unit failure event configuration
+	dmiEG.configuredEvents[dmi.EventIds_EVENT_PSU_FAILURE] = dmi.EventCfg{
+		EventId:      dmi.EventIds_EVENT_PSU_FAILURE,
+		IsConfigured: true,
+	}
+}
+
+// get the events list
+func getEventsList() []*dmi.EventCfg {
+	events := make(map[dmi.EventIds]dmi.EventCfg)
+	dmiEG.access.Lock()
+
+	for key, value := range dmiEG.configuredEvents {
+		events[key] = value
+	}
+
+	dmiEG.access.Unlock()
+
+	var toRet []*dmi.EventCfg
+	for _, v := range events {
+		eventConfig := v
+		toRet = append(toRet, &eventConfig)
+	}
+	logger.Debugf("Events list supported by device %+v", toRet)
+	return toRet
+}
+
+//UpdateEventConfig Adds/Updates the passed event configuration
+func UpdateEventConfig(newEventCfg *dmi.EventCfg) {
+	dmiEG.access.Lock()
+	dmiEG.configuredEvents[newEventCfg.GetEventId()] = *newEventCfg
+	dmiEG.access.Unlock()
+	logger.Infof("Events updated %v", newEventCfg)
+}
+
+// update Event MetaData
+func updateEventMetaData(c *dmi.Component, apiSrv *DmiAPIServer, evt *dmi.Event) *dmi.Event {
+	evt.EventMetadata = &dmi.EventMetaData{
+		DeviceUuid: &dmi.Uuid{
+			Uuid: apiSrv.uuid,
+		},
+		ComponentUuid: c.Uuid,
+		ComponentName: c.Name,
+	}
+	return evt
+}
+
+func sendOutEventOnKafka(event interface{}, apiSrv *DmiAPIServer) {
+	select {
+	case apiSrv.eventChannel <- event:
+	default:
+		logger.Debugf("Channel not ready dropping event")
+	}
+}
+
+func noThresholdEventGenerationFunc(eventID dmi.EventIds, cType dmi.ComponentType) {
+	for _, comp := range findComponentsOfType(dmiEG.apiSrv.root.Children, cType) {
+		var evnt dmi.Event
+		evnt.EventId = eventID
+		evnt = *updateEventMetaData(comp, dmiEG.apiSrv, &evnt)
+		evnt.RaisedTs = ptypes.TimestampNow()
+		logger.Debugf("Got a No Threshold event %+v", evnt)
+		sendOutEventOnKafka(evnt, dmiEG.apiSrv)
+		break
+	}
+}
+
+func thresholdEventGenerationFunc(eventID dmi.EventIds, cType dmi.ComponentType) {
+	eventGenerated := false
+	for _, comp := range findComponentsOfType(dmiEG.apiSrv.root.Children, cType) {
+		var evnt dmi.Event
+		evnt.EventId = eventID
+		evnt = *updateEventMetaData(comp, dmiEG.apiSrv, &evnt)
+		evnt.RaisedTs = ptypes.TimestampNow()
+		configuredEvents := make(map[dmi.EventIds]dmi.EventCfg)
+
+		dmiEG.access.Lock()
+		for key, value := range dmiEG.configuredEvents {
+			configuredEvents[key] = value
+		}
+		dmiEG.access.Unlock()
+
+		for k, v := range configuredEvents {
+			if k == eventID {
+				evnt.ThresholdInfo = &dmi.ThresholdInformation{
+					ObservedValue: &dmi.ValueType{
+						Val: &dmi.ValueType_IntVal{IntVal: int64(generateRand(int32(v.Thresholds.GetUpper().GetLow().GetIntVal()), int32(v.Thresholds.GetUpper().GetHigh().GetIntVal())))},
+					},
+					Thresholds: v.GetThresholds(),
+				}
+			}
+		}
+
+		logger.Debugf("Got Threshold event %v", evnt)
+		sendOutEventOnKafka(evnt, dmiEG.apiSrv)
+		eventGenerated = true
+		if eventGenerated {
+			break
+		}
+
+	}
+}
+
+// CreateEvent creates and the passed event if it's valid and sends it to the msg bus
+func (das *DmiAPIServer) CreateEvent(ctx context.Context, evt *bbsim.DmiEvent) (*bbsim.DmiCreateEventResponse, error) {
+	retFunc := func(code codes.Code, msg string) (*bbsim.DmiCreateEventResponse, error) {
+		res := &bbsim.DmiCreateEventResponse{}
+		res.StatusCode = int32(code)
+		res.Message = msg
+		return res, nil
+	}
+
+	if dmiEG.apiSrv == nil || dmiEG.apiSrv.root == nil || dmiEG.apiSrv.root.Children == nil {
+		// inventory might not yet be created
+		return retFunc(codes.Internal, "inventory do no exist")
+	}
+
+	eventID, exists := dmi.EventIds_value[evt.EventName]
+	if !exists {
+		return retFunc(codes.NotFound,
+			fmt.Sprintf("DMI Alarm not supported. Permissible values are %s", getValidEventNames()))
+	}
+
+	genUtil, exists := eventGenMap[dmi.EventIds(eventID)]
+	if !exists {
+		return retFunc(codes.Unimplemented, "Generation of this event not yet implemented")
+	}
+
+	genUtil.genFunc(dmi.EventIds(eventID), genUtil.componentType)
+
+	return retFunc(codes.OK, "DMI Event Indication Sent.")
+
+}
+
+func getValidEventNames() string {
+	s := ""
+	//keys := make([]string, len(dmi.EventIds_value)-1)
+	for k, v := range dmi.EventIds_value {
+		if v != 0 {
+			s = s + "\n" + k
+		}
+	}
+	return s
+}
diff --git a/internal/bbsim/dmiserver/dmi_events_mgmt.go b/internal/bbsim/dmiserver/dmi_events_mgmt.go
index 3fc3416..da1e8ae 100755
--- a/internal/bbsim/dmiserver/dmi_events_mgmt.go
+++ b/internal/bbsim/dmiserver/dmi_events_mgmt.go
@@ -18,6 +18,8 @@
 
 import (
 	"context"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
 
 	dmi "github.com/opencord/device-management-interface/go/dmi"
 )
@@ -25,11 +27,10 @@
 //ListEvents lists the supported events for the passed device
 func (dms *DmiAPIServer) ListEvents(ctx context.Context, req *dmi.HardwareID) (*dmi.ListEventsResponse, error) {
 	logger.Debugf("ListEvents called with request %+v", req)
-	//empty events
-	events := []*dmi.EventCfg{{}}
+	events := getEventsList()
+
 	return &dmi.ListEventsResponse{
 		Status: dmi.Status_OK_STATUS,
-		Reason: dmi.Reason_UNDEFINED_REASON,
 		Events: &dmi.EventsCfg{
 			Items: events,
 		},
@@ -39,6 +40,31 @@
 //UpdateEventsConfiguration updates the configuration of the list of events in the request
 func (dms *DmiAPIServer) UpdateEventsConfiguration(ctx context.Context, req *dmi.EventsConfigurationRequest) (*dmi.EventsConfigurationResponse, error) {
 	logger.Debugf("UpdateEventsConfiguration called with request %+v", req)
+
+	if req == nil || req.Operation == nil {
+		return &dmi.EventsConfigurationResponse{
+			Status: dmi.Status_ERROR_STATUS,
+			//TODO reason must be INVALID_PARAMS, currently this is not available in Device Management interface (DMI),
+			// change below reason with type INVALID_PARAMS once DMI is updated
+			Reason: dmi.Reason_UNDEFINED_REASON,
+		}, status.Errorf(codes.FailedPrecondition, "request is nil")
+	}
+
+	switch x := req.Operation.(type) {
+	case *dmi.EventsConfigurationRequest_Changes:
+		for _, eventConfig := range x.Changes.Items {
+			UpdateEventConfig(eventConfig)
+		}
+	case *dmi.EventsConfigurationRequest_ResetToDefault:
+		logger.Debugf("To be implemented later")
+	case nil:
+		// The field is not set.
+		logger.Debugf("Update request operation type is nil")
+		return &dmi.EventsConfigurationResponse{
+			Status: dmi.Status_UNDEFINED_STATUS,
+		}, nil
+	}
+
 	return &dmi.EventsConfigurationResponse{
 		Status: dmi.Status_OK_STATUS,
 	}, nil
diff --git a/internal/bbsim/dmiserver/dmi_hw_mgmt.go b/internal/bbsim/dmiserver/dmi_hw_mgmt.go
index cf6410d..cd0b0e9 100755
--- a/internal/bbsim/dmiserver/dmi_hw_mgmt.go
+++ b/internal/bbsim/dmiserver/dmi_hw_mgmt.go
@@ -34,7 +34,7 @@
 )
 
 const (
-	metricChannelSize = 100
+	kafkaChannelSize = 100
 )
 
 func getUUID(seed string) string {
@@ -66,9 +66,13 @@
 	dms.ponTransceiverCageUuids = make([]string, olt.NumPon)
 
 	// Start device metrics generator
-	dms.metricChannel = make(chan interface{}, metricChannelSize)
+	dms.metricChannel = make(chan interface{}, kafkaChannelSize)
 	StartMetricGenerator(dms)
 
+	// Start device event generator
+	dms.eventChannel = make(chan interface{}, kafkaChannelSize)
+	StartEventsGenerator(dms)
+
 	var components []*dmi.Component
 
 	// Create and store the component for transceivers and transceiver cages
@@ -113,11 +117,12 @@
 	}
 	components = append(components, fans...)
 
-	// Create 1 disk, 1 Processor and 1 ram
+	// Create 1 disk, 1 processor, 1 ram, 1 temperature sensor and power supply unit
 	components = append(components, createDiskComponent(0))
 	components = append(components, createProcessorComponent(0))
 	components = append(components, createMemoryComponent(0))
 	components = append(components, createInnerSurroundingTempComponentSensor(0))
+	components = append(components, createPowerSupplyComponent(0))
 
 	// create the root component
 	dms.root = &dmi.Component{
@@ -251,6 +256,25 @@
 	}
 }
 
+func createPowerSupplyComponent(psuIdx int) *dmi.Component {
+	psuName := fmt.Sprintf("Thermal/PSU/SystemPSU/%d", psuIdx)
+	psuSerial := fmt.Sprintf("bbsim-psu-serial-%d", psuIdx)
+	return &dmi.Component{
+		Name:         psuName,
+		Class:        dmi.ComponentType_COMPONENT_TYPE_POWER_SUPPLY,
+		Description:  "bbsim-psu",
+		Parent:       "",
+		ParentRelPos: 0,
+		SerialNum:    psuSerial,
+		MfgName:      "bbsim-psu",
+		IsFru:        false,
+		Uuid: &dmi.Uuid{
+			Uuid: getUUID(psuName),
+		},
+		State: &dmi.ComponentState{},
+	}
+}
+
 //StopManagingDevice stops management of a device and cleans up any context and caches for that device
 func (dms *DmiAPIServer) StopManagingDevice(ctx context.Context, req *dmi.StopManagingDeviceRequest) (*dmi.StopManagingDeviceResponse, error) {
 	logger.Debugf("StopManagingDevice API invoked")
@@ -452,10 +476,12 @@
 	nCtx, dms.mPublisherCancelFunc = context.WithCancel(context.Background())
 	// initialize a publisher
 	if err := InitializeDMKafkaPublishers(sarama.NewAsyncProducer, olt.ID, dms.kafkaEndpoint); err == nil {
-		// start a go routine which will read from channel and publish on kafka
+		// start a go routine which will read from channel and publish on kafka topic dm.metrics
 		go DMKafkaPublisher(nCtx, dms.metricChannel, "dm.metrics")
+		// start a go routine which will read from channel and publish on kafka topic dm.events
+		go DMKafkaPublisher(nCtx, dms.eventChannel, "dm.events")
 	} else {
-		logger.Errorf("Failed to start kafka publisher: %v", err)
+		logger.Errorf("Failed to start metric kafka publisher: %v", err)
 		return &dmi.SetRemoteEndpointResponse{Status: dmi.Status_ERROR_STATUS, Reason: dmi.Reason_KAFKA_ENDPOINT_ERROR}, err
 	}
 
diff --git a/internal/bbsim/dmiserver/dmi_kafka_producer.go b/internal/bbsim/dmiserver/dmi_kafka_producer.go
index 9ee0172..8955dfa 100755
--- a/internal/bbsim/dmiserver/dmi_kafka_producer.go
+++ b/internal/bbsim/dmiserver/dmi_kafka_producer.go
@@ -26,7 +26,7 @@
 	log "github.com/sirupsen/logrus"
 )
 
-var metricsProducer sarama.AsyncProducer
+var producer sarama.AsyncProducer
 
 // InitializeDMKafkaPublishers initializes  metrics kafka publisher
 func InitializeDMKafkaPublishers(NewAsyncProducer func([]string, *sarama.Config) (sarama.AsyncProducer, error), oltID int, msgBusEndPoint string) error {
@@ -37,9 +37,9 @@
 	config.Producer.Retry.Max = 5
 	config.Metadata.Retry.Max = 10
 	config.Metadata.Retry.Backoff = 10 * time.Second
-	config.ClientID = "BBSim-OLT-Metrics-" + strconv.Itoa(oltID)
+	config.ClientID = "BBSim-OLT-DMIServer-" + strconv.Itoa(oltID)
 
-	metricsProducer, err = NewAsyncProducer([]string{msgBusEndPoint}, config)
+	producer, err = NewAsyncProducer([]string{msgBusEndPoint}, config)
 	return err
 }
 
@@ -49,16 +49,16 @@
 loop:
 	for {
 		select {
-		case metric := <-ch:
-			log.Tracef("Writing to kafka topic(%s): %v", topic, metric)
-			jsonMet, err := json.Marshal(metric)
+		case data := <-ch:
+			log.Tracef("Writing to kafka topic(%s): %v", topic, data)
+			jsonData, err := json.Marshal(data)
 			if err != nil {
-				log.Errorf("Failed to get json metric %v", err)
+				log.Errorf("Failed to get json %v", err)
 				continue
 			}
-			metricsProducer.Input() <- &sarama.ProducerMessage{
+			producer.Input() <- &sarama.ProducerMessage{
 				Topic: topic,
-				Value: sarama.ByteEncoder(jsonMet),
+				Value: sarama.ByteEncoder(jsonData),
 			}
 		case <-ctx.Done():
 			log.Infof("Stopping DM Kafka Publisher for topic %s", topic)
diff --git a/internal/bbsim/dmiserver/dmi_metrics_mgmt.go b/internal/bbsim/dmiserver/dmi_metrics_mgmt.go
index cb88cc7..e23786f 100755
--- a/internal/bbsim/dmiserver/dmi_metrics_mgmt.go
+++ b/internal/bbsim/dmiserver/dmi_metrics_mgmt.go
@@ -79,7 +79,7 @@
 	if req == nil || req.GetMetricId() < 0 {
 		return &dmi.GetMetricResponse{
 			Status: dmi.Status_ERROR_STATUS,
-			//TODO reason must be INVALID_PARAMS, currently this is available in Device Management interface (DMI),
+			//TODO reason must be INVALID_PARAMS, currently this is not available in Device Management interface (DMI),
 			// change below reason with type INVALID_PARAMS once DMI is updated
 			Reason: dmi.Reason_UNDEFINED_REASON,
 			Metric: &dmi.Metric{},
diff --git a/internal/bbsimctl/commands/dmi_events.go b/internal/bbsimctl/commands/dmi_events.go
new file mode 100644
index 0000000..1608965
--- /dev/null
+++ b/internal/bbsimctl/commands/dmi_events.go
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package commands
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/jessevdk/go-flags"
+	"github.com/opencord/bbsim/api/bbsim"
+	"github.com/opencord/bbsim/internal/bbsimctl/config"
+	log "github.com/sirupsen/logrus"
+	"google.golang.org/grpc"
+)
+
+type DMIOptions struct {
+	Events DmiEventOptions `command:"events"`
+}
+
+type DmiEventCreate struct {
+	Args struct {
+		Name string
+	} `positional-args:"yes" required:"yes"`
+}
+
+type DmiEventOptions struct {
+	Create DmiEventCreate `command:"create"`
+}
+
+func RegisterDMICommands(parser *flags.Parser) {
+	_, _ = parser.AddCommand("dmi", "DMI Commands", "Commands to create events", &DMIOptions{})
+}
+
+func dmiEventGrpcClient() (bbsim.BBsimDmiClient, *grpc.ClientConn) {
+	conn, err := grpc.Dial(config.DmiConfig.Server, grpc.WithInsecure())
+	if err != nil {
+		log.Errorf("BBsimDmiClient connection failed  : %v", err)
+		return nil, conn
+	}
+	return bbsim.NewBBsimDmiClient(conn), conn
+}
+
+// Execute create event
+func (o *DmiEventCreate) Execute(args []string) error {
+	client, conn := dmiEventGrpcClient()
+	defer conn.Close()
+
+	ctx, cancel := context.WithTimeout(context.Background(), config.GlobalConfig.Grpc.Timeout)
+	defer cancel()
+
+	req := bbsim.DmiEvent{EventName: o.Args.Name}
+	res, err := client.CreateEvent(ctx, &req)
+	if err != nil {
+		log.Errorf("Cannot create DMI event: %v", err)
+		return err
+	}
+
+	fmt.Println(fmt.Sprintf("[Status: %d] %s", res.StatusCode, res.Message))
+	return nil
+}
diff --git a/internal/bbsimctl/commands/onualarms.go b/internal/bbsimctl/commands/onualarms.go
index fb1d00e..669c173 100755
--- a/internal/bbsimctl/commands/onualarms.go
+++ b/internal/bbsimctl/commands/onualarms.go
@@ -20,10 +20,11 @@
 import (
 	"context"
 	"fmt"
-	"github.com/opencord/bbsim/internal/common"
 	"os"
 	"strings"
 
+	"github.com/opencord/bbsim/internal/common"
+
 	"github.com/jessevdk/go-flags"
 	"github.com/olekukonko/tablewriter"
 	pb "github.com/opencord/bbsim/api/bbsim"
diff --git a/internal/bbsimctl/config/config.go b/internal/bbsimctl/config/config.go
index 7d11122..4bf762a 100644
--- a/internal/bbsimctl/config/config.go
+++ b/internal/bbsimctl/config/config.go
@@ -57,6 +57,13 @@
 	},
 }
 
+var DmiConfig = GlobalConfigSpec{
+	Server: "localhost:50075",
+	Grpc: GrpcConfigSpec{
+		Timeout: time.Second * 10,
+	},
+}
+
 func ProcessGlobalOptions() {
 	if len(GlobalOptions.Config) == 0 {
 		home, err := os.UserHomeDir()