public List<DeviceNotification> GetByDevices(int[] deviceIds, DeviceNotificationFilter filter = null) { List<DeviceNotification> notifications = null; if (filter != null && filter.GridInterval != null) { // use native MongoDB query for aggregation notifications = QueryWithGridInterval(deviceIds, filter); } else { var query = _mongo.DeviceNotifications.AsQueryable(); if (deviceIds != null) query = query.Where(e => deviceIds.Contains(e.DeviceID)); notifications = query.Filter(filter).ToList(); } var actualDeviceIds = notifications.Select(e => e.DeviceID).Distinct().ToArray(); var deviceLookup = _mongo.Devices.Find(Query<Device>.In(e => e.ID, actualDeviceIds)).ToDictionary(e => e.ID); foreach (var notification in notifications) notification.Device = deviceLookup[notification.DeviceID]; return notifications; }
public async Task<JArray> Get(string deviceGuid, DateTime? timestamp = null, string names = null, int? waitTimeout = null) { var device = GetDeviceEnsureAccess(deviceGuid); var start = timestamp ?? _timestampRepository.GetCurrentTimestamp(); var notificationNames = names != null ? names.Split(',') : null; if (waitTimeout <= 0) { var filter = new DeviceNotificationFilter { Start = start, IsDateInclusive = false, Notifications = notificationNames }; var notifications = DataContext.DeviceNotification.GetByDevice(device.ID, filter); return new JArray(notifications.Select(n => MapDeviceNotification(n, device))); } var config = DeviceHiveConfiguration.RestEndpoint; var delayTask = Task.Delay(1000 * Math.Min(config.NotificationPollMaxInterval, waitTimeout ?? config.NotificationPollDefaultInterval)); using (var waiterHandle = _notificationByDeviceIdWaiter.BeginWait(new object[] { device.ID }, notificationNames == null ? null : notificationNames.Cast<object>().ToArray())) { do { var filter = new DeviceNotificationFilter { Start = start, IsDateInclusive = false, Notifications = notificationNames }; var notifications = DataContext.DeviceNotification.GetByDevice(device.ID, filter); if (notifications != null && notifications.Any()) return new JArray(notifications.Select(n => MapDeviceNotification(n, device))); } while (await Task.WhenAny(waiterHandle.Wait(), delayTask) != delayTask); } return new JArray(); }
public List<DeviceNotification> GetByDevice(int deviceId, DeviceNotificationFilter filter = null) { using (var context = new DeviceHiveContext()) { var query = context.DeviceNotifications.Where(e => e.Device.ID == deviceId); return query.Filter(filter, FilterByGridInterval(filter == null ? null : filter.GridInterval)).ToList(); } }
public List<DeviceNotification> GetByDevices(int[] deviceIds, DeviceNotificationFilter filter = null) { using (var context = new DeviceHiveContext()) { var query = context.DeviceNotifications.Include(e => e.Device); if (deviceIds != null) query = query.Where(e => deviceIds.Contains(e.Device.ID)); return query.Filter(filter, FilterByGridInterval(filter == null ? null : filter.GridInterval)).ToList(); } }
public List<DeviceNotification> GetByDevice(int deviceId, DeviceNotificationFilter filter = null) { if (filter != null && filter.GridInterval != null) { // use native MongoDB query for aggregation return QueryWithGridInterval(new[] { deviceId }, filter); } return _mongo.DeviceNotifications.AsQueryable().Where(e => e.DeviceID == deviceId).Filter(filter).ToList(); }
public void SubsrcibeToDeviceNotifications(DateTime? timestamp, string[] deviceGuids = null, string[] names = null) { var subscriptionId = Guid.NewGuid(); var devices = GetDevices(deviceGuids, "GetDeviceNotification"); var deviceIds = devices == null ? null : devices.Select(d => d.ID).ToArray(); var initialNotificationList = GetInitialNotificationList(Connection, subscriptionId); lock (initialNotificationList) { _deviceSubscriptionManagerForNotifications.Subscribe(subscriptionId, Connection, deviceIds, names); SendResponse(new JProperty("subscriptionId", subscriptionId)); if (timestamp != null) { var filter = new DeviceNotificationFilter { Start = timestamp, IsDateInclusive = false, Notifications = names }; var initialNotifications = DataContext.DeviceNotification.GetByDevices(deviceIds, filter) .Where(n => IsDeviceAccessible(n.Device, "GetDeviceNotification")).ToArray(); foreach (var notification in initialNotifications) { initialNotificationList.Add(notification.ID); Notify(Connection, subscriptionId, notification, notification.Device, isInitialNotification: true); } } } }
private List<DeviceNotification> QueryWithGridInterval(int[] deviceIds, DeviceNotificationFilter filter) { if (filter == null) throw new ArgumentNullException("filter"); if (filter.GridInterval == null) throw new ArgumentException("GridInterval property of the filter is null!", "filter.GridInterval"); var periodStart = DateTime.SpecifyKind(new DateTime(2000, 1, 1), DateTimeKind.Utc); var periodMilliseconds = periodStart.Ticks / 10000; // prepare a list of operations for aggregation query var operations = new List<BsonDocument>(); // match by devices if (deviceIds != null) { operations.Add(new BsonDocument { { "$match", new BsonDocument { { "DeviceID", new BsonDocument { { "$in", new BsonArray(deviceIds) } } } } } }); } // match by filter criteria if (filter.Start != null) { operations.Add(new BsonDocument { { "$match", new BsonDocument { { "Timestamp", new BsonDocument { { filter.IsDateInclusive ? "$gte" : "$gt", filter.Start.Value } } } } } }); } if (filter.End != null) { operations.Add(new BsonDocument { { "$match", new BsonDocument { { "Timestamp", new BsonDocument { { filter.IsDateInclusive ? "$lte" : "$lt", filter.End.Value } } } } } }); } if (filter.Notification != null) { operations.Add(new BsonDocument { { "$match", new BsonDocument { { "Notification", filter.Notification } } } }); } if (filter.Notifications != null) { operations.Add(new BsonDocument { { "$match", new BsonDocument { { "Notification", new BsonDocument { { "$in", new BsonArray(filter.Notifications) } } } } } }); } // process grid interval aggregation operations.Add(new BsonDocument { { "$sort", new BsonDocument { { "Timestamp", 1 } } } }); operations.Add(new BsonDocument { { "$project", new BsonDocument { { "DeviceID", 1 }, { "Timestamp", 1 }, { "Notification", 1 }, { "Parameters", 1 }, { "tsmod", new BsonDocument { { "$mod", new BsonArray { new BsonDocument { { "$add", new BsonArray { new BsonDocument { { "$subtract", new BsonArray { "$Timestamp", periodStart } } }, periodMilliseconds } } }, new BsonInt64(1000 * filter.GridInterval.Value) } } } } } } }); operations.Add(new BsonDocument { { "$project", new BsonDocument { { "DeviceID", 1 }, { "Timestamp", 1 }, { "Notification", 1 }, { "Parameters", 1 }, { "tsinterval", new BsonDocument { { "$subtract", new BsonArray { new BsonDocument { { "$add", new BsonArray { new BsonDocument { { "$subtract", new BsonArray { "$Timestamp", periodStart } } }, periodMilliseconds } } }, new BsonString("$tsmod") } } } } } } }); operations.Add(new BsonDocument { { "$group", new BsonDocument { { "_id", new BsonDocument { { "tsinterval", "$tsinterval" }, { "DeviceID", "$DeviceID" }, { "Notification", "$Notification" } } }, { "ID", new BsonDocument { { "$first", "$_id" } } }, { "Timestamp", new BsonDocument { { "$first", "$Timestamp" } } }, { "DeviceID", new BsonDocument { { "$first", "$DeviceID" } } }, { "Notification", new BsonDocument { { "$first", "$Notification" } } }, { "Parameters", new BsonDocument { { "$first", "$Parameters" } } } } } }); operations.Add(new BsonDocument { { "$project", new BsonDocument { { "_id", "$ID" }, { "DeviceID", 1 }, { "Timestamp", 1 }, { "Notification", 1 }, { "Parameters", 1 } } } }); // apply sorting and pagination if (filter.SortField != DeviceNotificationSortField.None) { var sortOrder = filter.SortOrder == SortOrder.ASC ? 1 : -1; switch (filter.SortField) { case DeviceNotificationSortField.Timestamp: operations.Add(new BsonDocument { { "$sort", new BsonDocument { { "Timestamp", sortOrder } } } }); break; case DeviceNotificationSortField.Notification: operations.Add(new BsonDocument { { "$sort", new BsonDocument { { "Notification", sortOrder }, { "Timestamp", sortOrder } } } }); break; } } if (filter.Skip != null) { operations.Add(new BsonDocument { { "$skip", filter.Skip.Value } }); } if (filter.Take != null) { operations.Add(new BsonDocument { { "$limit", filter.Take.Value } }); } // run the aggregation query var result = _mongo.DeviceNotifications.Aggregate(operations); return result.ResultDocuments.Select(BsonSerializer.Deserialize<DeviceNotification>).ToList(); }