public async Task ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> events)
        {
            try
            {
                var now = DateTime.UtcNow;

                foreach (var eventData in events)
                {
                    // We don't care about messages that are older than bufferTimeInterval
                    if ((eventData.EnqueuedTimeUtc + bufferTimeInterval) >= now)
                    {
                        // Get message from the eventData body and convert JSON string into message object
                        string eventBodyAsString = Encoding.UTF8.GetString(eventData.GetBytes());

                        // There can be several messages in one
                        IList <IDictionary <string, object> > messagePayloads;
                        try
                        {
                            // Attempt to deserialze event body as single JSON message
                            messagePayloads = new List <IDictionary <string, object> >
                            {
                                JsonConvert.DeserializeObject <IDictionary <string, object> >(eventBodyAsString)
                            };
                        }
                        catch
                        {
                            // Not a single JSON message: attempt to deserialize as array of messages

                            // Azure Stream Analytics Preview generates invalid JSON for some multi-values queries
                            // Workaround: turn concatenated json objects (ivalid JSON) into array of json objects (valid JSON)
                            if (eventBodyAsString.IndexOf("}{") >= 0)
                            {
                                eventBodyAsString = eventBodyAsString.Replace("}{", "},{");
                            }
                            if (eventBodyAsString.IndexOf("}\r\n{") >= 0)
                            {
                                eventBodyAsString = eventBodyAsString.Replace("}\r\n{", "},{");
                            }
                            if (!eventBodyAsString.EndsWith("]"))
                            {
                                eventBodyAsString = eventBodyAsString + "]";
                            }
                            if (!eventBodyAsString.StartsWith("["))
                            {
                                eventBodyAsString = "[" + eventBodyAsString.Substring(eventBodyAsString.IndexOf("{"));
                            }

                            messagePayloads = JsonConvert.DeserializeObject <IList <IDictionary <string, object> > >(eventBodyAsString);
                        }

                        var rnd = new Random();
                        foreach (var messagePayload in messagePayloads)
                        {
                            // Read time value
                            if (messagePayload.ContainsKey("timecreated"))
                            {
                                messagePayload["time"] = messagePayload["timecreated"];
                            }
                            if (messagePayload.ContainsKey("timearrived"))
                            {
                                messagePayload["time"] = messagePayload["timearrived"];
                            }
                            // process an alert
                            if (messagePayload.ContainsKey("alerttype") && messagePayload.ContainsKey("timecreated"))
                            {
                                Debug.Print("Alert message received!");

                                // If the IoTHub service client has not yet been created, go create it.
                                if (IoTHub == null)
                                {
                                    IoTHub = new IoTHubHelper(Microsoft.Azure.CloudConfigurationManager.GetSetting("Azure.IoT.IoTHub.ConnectionString"));
                                }

                                // Send alert to device
                                if (IoTHub != null)
                                {
                                    var alertMessage = JsonConvert.SerializeObject(messagePayload).ToString();
                                    IoTHub.SendMessage(messagePayload["guid"].ToString(), alertMessage);
                                }

                                DateTime time = DateTime.Parse(messagePayload["timecreated"].ToString());
                                // find the nearest point
                                lock (sortedDataBuffer)
                                {
                                    int    idx       = SearchHelper.FindFirstIndexGreaterThanOrEqualTo(sortedDataBuffer, time);
                                    bool   found     = false;
                                    string alertType = messagePayload["alerttype"] as string;

                                    if (idx >= sortedDataBuffer.Values.Count)
                                    {
                                        idx = sortedDataBuffer.Values.Count - 1;
                                    }

                                    while (idx >= 0)
                                    {
                                        List <IDictionary <string, object> > dictList = sortedDataBuffer.Values[idx];
                                        foreach (IDictionary <string, object> dict in dictList)
                                        {
                                            if (
                                                (dict.ContainsKey("guid") && messagePayload.ContainsKey("guid") && messagePayload["guid"].ToString() == dict["guid"].ToString())
                                                &&
                                                (dict.ContainsKey("measurename") && messagePayload.ContainsKey("measurename") && messagePayload["measurename"].ToString() == dict["measurename"].ToString())
                                                &&
                                                (!messagePayload.ContainsKey("displayname") || dict.ContainsKey("displayname") && messagePayload["measurename"].ToString() == dict["measurename"].ToString())
                                                )
                                            {
                                                // fill anomaly message
                                                if (!messagePayload.ContainsKey("value"))
                                                {
                                                    messagePayload["value"] = dict["value"];
                                                }
                                                if (!messagePayload.ContainsKey("displayname") && dict.ContainsKey("displayname"))
                                                {
                                                    messagePayload["displayname"] = dict["displayname"];
                                                }
                                                if (!messagePayload.ContainsKey("time"))
                                                {
                                                    messagePayload["time"] = messagePayload["timecreated"];
                                                }
                                                found = true;
                                                break;
                                            }
                                        }
                                        if (found)
                                        {
                                            break;
                                        }
                                        idx--;
                                    }
                                }
                            }

                            if (messagePayload.ContainsKey("guid"))
                            {
                                var    guid = messagePayload["guid"].ToString();
                                double val  = Convert.ToDouble(messagePayload["value"]);

                                if (!MinMaxValue.ContainsKey(guid))
                                {
                                    MinMaxValue.Add(guid, new MinMax {
                                        min = val, max = val
                                    });
                                }

                                MinMax tmp = MinMaxValue[messagePayload["guid"].ToString()];
                                if (tmp.min > val)
                                {
                                    tmp.min = val;
                                }
                                if (tmp.max < val)
                                {
                                    tmp.max = val;
                                }
                            }
                            // We want to read the time value from the message itself.
                            // If none is found we will use the enqueued time
                            DateTime messageTimeStamp = new DateTime();
                            if (messagePayload.ContainsKey("time"))
                            {
                                messageTimeStamp = DateTime.Parse(messagePayload["time"].ToString());

                                //if (GenerateAnomalies && rnd.Next(100) >= 95)
                                //{
                                //    messagePayload.Add("alerttype", "testType");
                                //    messagePayload.Add("dsplalert", "testAlert");
                                //    messagePayload.Add("message", "Anomaly detected by Azure ML model.");
                                //    messagePayload.Add("timestart", messagePayload["time"]);

                                //    // correct value
                                //    if (rnd.Next(2) == 1)
                                //        messagePayload["value"] = MinMaxValue[messagePayload["guid"].ToString()].max * (1.01 + 0.05 * rnd.Next(100) / 100);
                                //    else
                                //        messagePayload["value"] = MinMaxValue[messagePayload["guid"].ToString()].min * (0.99 - 0.05 * rnd.Next(100) / 100);
                                //}
                            }
                            else if (messagePayload.ContainsKey("timestart"))
                            {
                                messageTimeStamp = DateTime.Parse(messagePayload["timestart"].ToString());
                            }
                            else
                            {
                                messageTimeStamp = eventData.EnqueuedTimeUtc;
                            }

                            // Build up the list of devices seen so far (in lieu of a formal device repository)
                            // Also keep the last message received per device (not currently used in the sample)
                            if (messagePayload.ContainsKey("guid") && !messagePayload.ContainsKey("valueAvg"))
                            {
                                string guid = messagePayload["guid"].ToString();
                                if (guid != null)
                                {
                                    WebSocketEventProcessor.g_devices.TryAdd(guid, messagePayload);
                                }
                            }

                            // Notify clients
                            MyWebSocketHandler.SendToClients(messagePayload);

                            // Buffer messages so we can resend them to clients that connect later
                            // or when a client requests data for a different device

                            // Lock to guard against concurrent reads from client resend
                            lock (sortedDataBuffer)
                            {
                                if (!sortedDataBuffer.ContainsKey(messageTimeStamp))
                                {
                                    sortedDataBuffer.Add(messageTimeStamp, new List <IDictionary <string, object> >());
                                }

                                sortedDataBuffer[messageTimeStamp].Add(messagePayload);
                            }
                        }
                    }
                    else
                    {
                        Debug.Print("Received old message timestamped:" + eventData.EnqueuedTimeUtc.ToString());
                    }
                }

                //Call checkpoint every minute
                if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(1))
                {
                    await context.CheckpointAsync();

                    lock (this)
                    {
                        this.checkpointStopWatch.Restart();
                    }

                    // trim data buffer to keep only last 10 minutes of data
                    lock (sortedDataBuffer)
                    {
                        DateTime oldDataPoint = now - bufferTimeInterval;
                        // find the closest point
                        int idx = SearchHelper.FindFirstIndexGreaterThanOrEqualTo(sortedDataBuffer, oldDataPoint);
                        // trim
                        while (idx > 0 && sortedDataBuffer.Count > 0 && sortedDataBuffer.Keys[0] <= oldDataPoint)
                        {
                            sortedDataBuffer.RemoveAt(0);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Trace.TraceError("Error processing events in EH {0}, partition {1}: {0}",
                                 context.EventHubPath, context.Lease.PartitionId, e.Message);
            }
        }