public void StartEventMonitor(Brick brick)
        {
            Dictionary <int, InputPort> inputPorts = brick.IOPort.Input.Ports;
            Buttons      buttons = brick.Buttons;
            Battery      battery = brick.Battery;
            BrickConsole console = brick.Console;

            int INTERVAL = Brick.Options.EventMonitor.Interval;

            Task task = Task.Factory.StartNew(async() =>
            {
                while (!_socket.CancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        //do not overload event message pump
                        if (_socket.EventBuffer.Count == 0)
                        {
                            byte[] batch = null;
                            ushort index = 0;

                            ushort buttonByteLength  = 0;
                            ushort batteryByteLength = 0;
                            ushort warningByteLength = 0;

                            Dictionary <InputPort, DataType> triggeredPorts = new Dictionary <InputPort, DataType>();
                            using (PayLoadBuilder cb = new PayLoadBuilder())
                            {
                                foreach (int key in inputPorts.Keys)
                                {
                                    InputPort port = inputPorts[key];
                                    if (port.Status != PortStatus.OK)
                                    {
                                        continue;                               // no device connected so continue
                                    }
                                    InputDevice device = (InputDevice)port.Device;

                                    if (!device.MonitorEvents)
                                    {
                                        continue;                                   // device will get value on manual poll
                                    }
                                    DataType type = device.BatchCommand(cb, index); // get batchcommand
                                    if (type == DataType.NONE)
                                    {
                                        continue;
                                    }

                                    index += type.ByteLength();
                                    triggeredPorts.Add(port, type);
                                }


                                buttonByteLength = buttons.BatchCommand(cb, index);
                                index           += buttonByteLength;

                                batteryByteLength = battery.BatchCommand(cb, index);
                                index            += batteryByteLength;

                                warningByteLength = console.BatchCommand(cb, index);
                                index            += warningByteLength;

                                batch = cb.ToBytes();
                            }

                            //no need to send batch, it has no content.
                            if (batch.Length == 0)
                            {
                                try
                                {
                                    await Task.Delay(INTERVAL, _socket.CancellationToken);
                                }
                                catch (TaskCanceledException) { }
                                continue;
                            }

                            Command cmd = null;
                            using (CommandBuilder cb = new CommandBuilder(CommandType.DIRECT_COMMAND_REPLY, index, 0, useEventId: true))
                            {
                                cb.Raw(batch);
                                cmd = cb.ToCommand();
                            }

                            Response response = await Brick.Socket.Execute(cmd, true);

                            if (response.Type == ResponseType.ERROR)
                            {
                                continue;
                            }

                            byte[] data = response.PayLoad;
                            if (data.Length != index)
                            {
                                if (!_socket.CancellationToken.IsCancellationRequested)
                                {
                                    throw new FirmwareException(response);
                                }
                                else
                                {
                                    continue;
                                }
                            }


                            index = 0;
                            foreach (InputPort port in triggeredPorts.Keys)
                            {
                                InputDevice device = (InputDevice)port.Device;

                                bool hasChanged = false;
                                DataType type   = triggeredPorts[port];
                                switch (type)
                                {
                                case DataType.DATA8:
                                    {
                                        hasChanged = device.SetDeviceValue(data[index]);
                                        break;
                                    }

                                case DataType.DATAF:
                                    {
                                        hasChanged = device.SetDeviceValue(BitConverter.ToSingle(data, index));
                                        break;
                                    }

                                case DataType.DATA32:
                                    {
                                        hasChanged = device.SetDeviceValue(BitConverter.ToInt32(data, index));
                                        break;
                                    }

                                case DataType.DATA16:
                                    {
                                        hasChanged = device.SetDeviceValue(BitConverter.ToInt16(data, index));
                                        break;
                                    }

                                case DataType.DATA_A4:
                                    {
                                        byte[] values = new byte[4];
                                        Array.Copy(data, index, values, 0, 4);
                                        hasChanged = device.SetDeviceValue(values);
                                        break;
                                    }
                                }

                                index += type.ByteLength();
                            }

                            if (buttonByteLength > 0)
                            {
                                byte[] buttonData = new byte[buttonByteLength];
                                Array.Copy(data, index, buttonData, 0, buttonByteLength);
                                buttons.BatchCommandReturn(buttonData);
                                index += buttonByteLength;
                            }

                            if (batteryByteLength > 0)
                            {
                                byte[] batteryData = new byte[batteryByteLength];
                                Array.Copy(data, index, batteryData, 0, batteryByteLength);
                                battery.SetValue(batteryData);
                                index += batteryByteLength;
                            }

                            if (warningByteLength > 0)
                            {
                                console.SetValue(data[index]);
                                index += warningByteLength;
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Brick.Logger.LogError(e, e.Message);
                    }

                    try
                    {
                        await Task.Delay(INTERVAL, _socket.CancellationToken);
                    }
                    catch (TaskCanceledException) { }
                }
            }, _socket.CancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
        }