public async Task<Result> RegisterAsync(DeviceValue deviceValue, Device device, CancellationToken cancellationToken)
        {
            if (deviceValue == null)
                return Result.ReportError("You must send a device value when registering a device value!");

            if (device == null)
                return Result.ReportError("You must send a device when registering a device value!");

            using (var context = new ZvsContext(EntityContextConnection))
            {
                var existingDv =
                    await
                        context.DeviceValues.FirstOrDefaultAsync(o => o.UniqueIdentifier == deviceValue.UniqueIdentifier
                                                                      && o.DeviceId == device.Id, cancellationToken);

                if (existingDv == null)
                {
                    //NEW VALUE
                    context.DeviceValues.Add(deviceValue);
                    return await context.TrySaveChangesAsync(cancellationToken);
                }

                var hasChanged = false;
                PropertyChangedEventHandler action = (s, a) => hasChanged = true;
                existingDv.PropertyChanged += action;
                
                existingDv.CommandClass = deviceValue.CommandClass;
                existingDv.CustomData1 = deviceValue.CustomData1;
                existingDv.CustomData2 = deviceValue.CustomData2;
                existingDv.Genre = deviceValue.Genre;
                existingDv.Index = deviceValue.Index;
                existingDv.IsReadOnly = deviceValue.IsReadOnly;
                existingDv.Description = deviceValue.Description;
                existingDv.Name = deviceValue.Name;
                existingDv.ValueType = deviceValue.ValueType;
                existingDv.Value = deviceValue.Value;
                existingDv.IsReadOnly = deviceValue.IsReadOnly;

                existingDv.PropertyChanged -= action;

                if (hasChanged)
                {
                    return await context.TrySaveChangesAsync(cancellationToken);
                }

                return Result.ReportSuccess("Nothing to update");
            }
        }
        public async Task RegisterAsyncNewDeviceValueTest()
        {
            //arrange 
            var dbConnection = new StubIEntityContextConnection { NameOrConnectionStringGet = () => "dvb-RegisterAsyncNewDeviceValueTest" };
            Database.SetInitializer(new CreateFreshDbInitializer());

            var dvb = new DeviceValueBuilder( dbConnection);

            var device = UnitTesting.CreateFakeDevice();
            using (var context = new ZvsContext(dbConnection))
            {
                context.Devices.Add(device);
                await context.SaveChangesAsync();

                var deviceValue = new DeviceValue
                {
                    Description = "Testing Value Description Here",
                    Name = "Test Value",
                    ValueType = DataType.BOOL,
                    Value = true.ToString(),
                    DeviceId = device.Id
                };

                //act
                var result = await dvb.RegisterAsync(deviceValue, device, CancellationToken.None);
                var dv = await context.DeviceValues.FirstOrDefaultAsync(o => o.Name == deviceValue.Name);


                //assert 
                Assert.IsFalse(result.HasError, result.Message);
                Assert.IsNotNull(dv, "Registered device value count not be found in database.");
                Console.WriteLine(result.Message);
            }
        }
        public async Task RegisterAsyncNothingToUpdateTest()
        {
            //arrange 
            var dbConnection = new StubIEntityContextConnection { NameOrConnectionStringGet = () => "dvb-RegisterAsyncNothingToUpdateTest" };
            Database.SetInitializer(new CreateFreshDbInitializer());

            var dvb = new DeviceValueBuilder(dbConnection);

            var device = UnitTesting.CreateFakeDevice();
            using (var context = new ZvsContext(dbConnection))
            {
                context.Devices.Add(device);
                var deviceValue = new DeviceValue
                {
                    UniqueIdentifier = "UNIT_TESTING_VALUE1",
                    CommandClass = "Command Class 1",
                    CustomData1 = "Custom Data 1",
                    CustomData2 = "Custom Data 2",
                    Description = "Testing Value Description Here",
                    Name = "Test Value",
                    ValueType = DataType.BOOL,
                    Value = true.ToString(),
                    Genre = "Genre",
                    Index = "Index",
                    IsReadOnly = true
                };
                device.Values.Add(deviceValue);
                await context.SaveChangesAsync();

                //act
                var result = await dvb.RegisterAsync(deviceValue, device, CancellationToken.None);
                var dv = await context.DeviceValues.FirstOrDefaultAsync(o => o.Name == deviceValue.Name);

                //assert 
                Assert.IsFalse(result.HasError, result.Message);
                Assert.IsNotNull(dv, "Registered device value count not be found in database.");
                Console.WriteLine(result.Message);
            }

        }
        public async Task LessThanInvalidValuesTest()
        {
            //Arrange 
            var dbConnection = new StubIEntityContextConnection { NameOrConnectionStringGet = () => "Trigger-LessThanInvalidValuesTest" };
            Database.SetInitializer(new CreateFreshDbInitializer());

            var logEntries = new List<LogEntry>();
            var ranstoredCommands = new List<int>();
            var log = new StubIFeedback<LogEntry>
            {
                ReportAsyncT0CancellationToken = (e, c) =>
                {
                    Console.WriteLine(e.ToString());
                    logEntries.Add(e);
                    return Task.FromResult(0);
                }
            };

            var commandProcessor = new StubICommandProcessor
            {
                RunCommandAsyncNullableOfInt32StringStringCancellationToken = ( commandId, argument, argument2, cancellationToken) =>
                {
                    if (commandId.HasValue) ranstoredCommands.Add(commandId.Value);
                    return Task.FromResult(Result.ReportSuccess());
                }
            };


            Database.SetInitializer(new CreateFreshDbInitializer());

            var cts = new CancellationTokenSource();
            var triggerManager = new TriggerRunner(log, commandProcessor, dbConnection);
            await triggerManager.StartAsync(cts.Token);

            var cmd = new Command();
            var dv = new DeviceValue
            {
                Value = "first value",
                ValueType = DataType.STRING,
                Triggers = new ObservableCollection<DeviceValueTrigger> { 
                    new DeviceValueTrigger
                {
                     Name = "trigger1",
                     IsEnabled = true,
                     Operator = TriggerOperator.LessThan,
                     Value = "a",
                     Command = cmd
                } }
            };

            var device = UnitTesting.CreateFakeDevice();
            device.Values.Add(dv);

            using (var context = new ZvsContext(dbConnection))
            {
                context.Devices.Add(device);
                var r = await context.TrySaveChangesAsync(cts.Token);
                Assert.IsFalse(r.HasError, r.Message);
                dv.Value = "3";

                //Act
                var r2 = await context.TrySaveChangesAsync(cts.Token);
                Assert.IsFalse(r2.HasError, r2.Message);
            }

            await Task.Delay(700, cts.Token);
            await triggerManager.StopAsync(cts.Token);

            //Assert
            Assert.IsTrue(logEntries.Any(o => o.Level == LogEntryLevel.Warn), "Expected some warning log entries");
            Assert.IsTrue(ranstoredCommands.Count == 0, "Trigger runner did not run the correct amount of commands.");
        }
        public async Task QuickFireTriggerTest()
        {
            var dbConnection = new StubIEntityContextConnection { NameOrConnectionStringGet = () => "Trigger-QuickFireTriggerTest" };
            Database.SetInitializer(new CreateFreshDbInitializer());

            var logEntries = new List<LogEntry>();
            var ranstoredCommands = new List<int>();

            //Arrange 
            var log = new StubIFeedback<LogEntry>
            {
                ReportAsyncT0CancellationToken = (e, c) =>
                {
                    Console.WriteLine(e.ToString());
                    logEntries.Add(e);
                    return Task.FromResult(0);
                }
            };

            var commandProcessor = new StubICommandProcessor
            {
                RunCommandAsyncNullableOfInt32StringStringCancellationToken = ( commandId, argument, argument2, cancellationToken) =>
                {
                    if (commandId.HasValue) ranstoredCommands.Add(commandId.Value);
                    return Task.FromResult(Result.ReportSuccess());
                }
            };

            var cts = new CancellationTokenSource();
            var triggerManager = new TriggerRunner(log, commandProcessor, dbConnection);
            await triggerManager.StartAsync(cts.Token);

            var cmd = new Command();
            var dv = new DeviceValue
            {
                Value = "first value",
                ValueType = DataType.STRING,
                Triggers = new ObservableCollection<DeviceValueTrigger> { 
                    new DeviceValueTrigger
                {
                     Name = "trigger1",
                     IsEnabled = true,
                     Operator = TriggerOperator.EqualTo,
                     Value = "some unique value",
                     Command = cmd
                } }
            };

            var device = UnitTesting.CreateFakeDevice();
            device.Values.Add(dv);

            //Act
            using (var context = new ZvsContext(dbConnection))
            {
                context.Devices.Add(device);
                await context.TrySaveChangesAsync(cts.Token);

                dv.Value = "Not It!";
                await context.TrySaveChangesAsync(cts.Token);

                dv.Value = "not this one";
                await context.TrySaveChangesAsync(cts.Token);

                dv.Value = "some unique value";
                await context.TrySaveChangesAsync(cts.Token);

                dv.Value = "not it";
                await context.TrySaveChangesAsync(cts.Token);

                dv.Value = "some unique value";
                await context.TrySaveChangesAsync(cts.Token);

                Console.WriteLine(context.DeviceValueTriggers.Count());
            }

            await Task.Delay(700, cts.Token);
            await triggerManager.StopAsync(cts.Token);

            //Assert
            Assert.IsTrue(logEntries.All(o => o.Level == LogEntryLevel.Info), "Expected only info type log entries");
            Assert.IsTrue(ranstoredCommands.Count == 2, "Trigger runner did not run the correct amount of commands.");
            Assert.IsTrue(ranstoredCommands.All(o => o == cmd.Id), "Scheduled task runner did not run the correct command.");
        }
Example #6
0
        private async Task AddOrUpdateValue(string name, string value, int deviceId, DataType dataType, string valueName,
                                            string genre, ZvsContext context)
        {
            context.DeviceValues.FirstOrDefaultAsync(d => d.DeviceId == deviceId && d.Name == valueName)
                   .ContinueWith(t
                                 =>
                       {
                           DeviceValue dv = t.Result;
                           if (dv == null)
                           {
                               dv = new DeviceValue
                                   {
                                       DeviceId = deviceId,
                                       Name = valueName,
                                       ValueType = dataType,
                                       Genre = genre
                                   };

                               context.DeviceValues.Add(dv);
                           }

                           dv.Value = value;

                           context.TrySaveChangesAsync().ContinueWith(tt =>
                               {
                                   if (tt.Result.HasError)
                                       ZvsEngine.log.Error(tt.Result.Message);

                               }).Wait();

                       }).Wait();


        }