public async void CreatePingDataSourceSdtOnEmptyDeviceGroup()
        {
            const string deviceGroupName = "CreatePingDataSourceSdtOnEmptyDeviceGroupUnitTest";

            // Ensure DeviceGroup is NOT present
            var deviceGroup = await PortalClient
                              .GetDeviceGroupByFullPathAsync(deviceGroupName)
                              .ConfigureAwait(false);

            if (deviceGroup != null)
            {
                await PortalClient
                .DeleteAsync(deviceGroup)
                .ConfigureAwait(false);
            }

            // Create DeviceGroup
            deviceGroup = await PortalClient
                          .CreateAsync(new DeviceGroupCreationDto
            {
                ParentId = "1",
                Name     = deviceGroupName
            })
                          .ConfigureAwait(false);

            // Get ping DataSource
            var dataSource = (await PortalClient
                              .GetAllAsync(new Filter <DataSource>
            {
                FilterItems = new List <FilterItem <DataSource> >
                {
                    new Eq <DataSource>(nameof(DataSource.Name), "Ping")
                }
            })
                              .ConfigureAwait(false))
                             .SingleOrDefault();

            // Create Scheduled Downtime
            var sdtCreationDto = new DeviceGroupScheduledDownTimeCreationDto(deviceGroup.Id)
            {
                Comment = "Created by Unit Test",
                StartDateTimeEpochMs = DateTime.UtcNow.MillisecondsSinceTheEpoch(),
                EndDateTimeEpochMs   = DateTime.UtcNow.AddDays(7).MillisecondsSinceTheEpoch(),
                RecurrenceType       = ScheduledDownTimeRecurrenceType.OneTime,
                DataSourceId         = dataSource.Id,
                DataSourceName       = dataSource.Name
            };

            // Check the created SDT looks right
            var createdSdt = await PortalClient
                             .CreateAsync(sdtCreationDto)
                             .ConfigureAwait(false);

            Assert.NotNull(createdSdt);

            // Clean up
            await PortalClient
            .DeleteAsync <ScheduledDownTime>(createdSdt.Id)
            .ConfigureAwait(false);

            // Remove the device group
            await PortalClient
            .DeleteAsync(deviceGroup)
            .ConfigureAwait(false);
        }
        public async void AddAndDeleteADeviceGroupSdt()
        {
            var          portalClient   = PortalClient;
            const string initialComment = "Woo";
            const int    deviceGroupId  = 1;         // The root
            var          sdtCreationDto = new DeviceGroupScheduledDownTimeCreationDto(deviceGroupId)
            {
                Comment = initialComment,
                StartDateTimeEpochMs = DateTime.UtcNow.MillisecondsSinceTheEpoch(),
                EndDateTimeEpochMs   = DateTime.UtcNow.AddDays(7).MillisecondsSinceTheEpoch(),
                RecurrenceType       = ScheduledDownTimeRecurrenceType.OneTime
            };

            // Check the created SDT looks right
            var createdSdt = await portalClient.CreateAsync(sdtCreationDto).ConfigureAwait(false);

            Assert.Equal(initialComment, createdSdt.Comment);
            Assert.Equal(deviceGroupId, createdSdt.DeviceGroupId);

            // Check the re-fetched SDT looks right
            var refetchSdt = await portalClient.GetAsync <ScheduledDownTime>(createdSdt.Id).ConfigureAwait(false);

            Assert.Equal(initialComment, refetchSdt.Comment);
            Assert.Equal(deviceGroupId, refetchSdt.DeviceGroupId);

            // Update
            const string newComment = "Yay";

            createdSdt.Comment = newComment;
            await portalClient.PutStringIdentifiedItemAsync(createdSdt).ConfigureAwait(false);

            // Check the re-fetched SDT looks right
            refetchSdt = await portalClient.GetAsync <ScheduledDownTime>(createdSdt.Id).ConfigureAwait(false);

            Assert.Equal(newComment, refetchSdt.Comment);
            Assert.Equal(deviceGroupId, refetchSdt.DeviceGroupId);

            // Get all scheduled downtimes (we have created one, so at least that one should be there)
            var scheduledDownTimes = await portalClient.GetAllAsync(new Filter <ScheduledDownTime>
            {
                FilterItems = new List <FilterItem <ScheduledDownTime> >
                {
                    new Eq <ScheduledDownTime>(nameof(ScheduledDownTime.Type), "DeviceGroupSDT"),
                    new Gt <ScheduledDownTime>(nameof(ScheduledDownTime.StartDateTimeMs), DateTime.UtcNow.AddDays(-30).SecondsSinceTheEpoch())
                }
            }).ConfigureAwait(false);

            Assert.NotNull(scheduledDownTimes);
            Assert.NotEmpty(scheduledDownTimes);

            // Get them all individually
            foreach (var sdt in scheduledDownTimes)
            {
                var refetchedSdt = await portalClient.GetAsync <ScheduledDownTime>(sdt.Id).ConfigureAwait(false);

                Assert.Equal(sdt.Id, refetchedSdt.Id);
                Assert.Equal(sdt.DeviceGroupId, refetchedSdt.DeviceGroupId);
                Assert.Equal(sdt.Comment, refetchedSdt.Comment);
            }

            // Delete
            await portalClient.DeleteAsync <ScheduledDownTime>(createdSdt.Id).ConfigureAwait(false);
        }