internal async Task<Result> ExecuteDeviceCommandAsync(DeviceCommand command, string argument, string argument2, CancellationToken cancellationToken) { using (var context = new ZvsContext(EntityContextConnection)) { var deviceCommand = await context.DeviceCommands .Include(o => o.Device) .Include(o => o.Device.Type) .Include(o => o.Device.Type.Adapter) .FirstOrDefaultAsync(o => o.Id == command.Id, cancellationToken); if (deviceCommand == null) return Result.ReportErrorFormat("Cannot locate device command with id of {0}", command.Id); var commandAction = string.Format("{0}{1} ({3}) on {2} ({4})", deviceCommand.Name, string.IsNullOrEmpty(argument) ? "" : " " + argument, deviceCommand.Device.Name, deviceCommand.Id, deviceCommand.Device.Id); var aGuid = deviceCommand.Device.Type.Adapter.AdapterGuid; var adapter = AdapterManager.FindZvsAdapter(aGuid); if (adapter == null) { return Result.ReportErrorFormat("{0} failed, device adapter is not loaded!", commandAction); } if (!adapter.IsEnabled) return Result.ReportErrorFormat("{0} failed because the '{1}' adapter is disabled", commandAction, deviceCommand.Device.Type.Adapter.Name); await adapter.ProcessDeviceCommandAsync(deviceCommand.Device, deviceCommand, argument, argument2); return Result.ReportSuccessFormat("{0} complete", commandAction); } }
public async Task<Result> RegisterAsync(int deviceId, DeviceCommand deviceCommand, CancellationToken cancellationToken) { if (deviceCommand == null) return Result.ReportError("Device command is null"); using (var context = new ZvsContext(EntityContextConnection)) { var device = await context.Devices.FirstOrDefaultAsync(o => o.Id == deviceId, cancellationToken); if(device == null ) return Result.ReportError("Invalid device id"); //Does device type exist? var existingDc = await context.DeviceCommands .Include(o => o.Options) .FirstOrDefaultAsync(c => c.UniqueIdentifier == deviceCommand.UniqueIdentifier && c.DeviceId == deviceId, cancellationToken); if (existingDc == null) { device.Commands.Add(deviceCommand); return await context.TrySaveChangesAsync(cancellationToken); } var changed = false; PropertyChangedEventHandler handler = (s, a) => changed = true; existingDc.PropertyChanged += handler; existingDc.ArgumentType = deviceCommand.ArgumentType; existingDc.CustomData1 = deviceCommand.CustomData1; existingDc.CustomData2 = deviceCommand.CustomData2; existingDc.Description = deviceCommand.Description; existingDc.Name = deviceCommand.Name; existingDc.Help = deviceCommand.Help; existingDc.SortOrder = deviceCommand.SortOrder; existingDc.PropertyChanged -= handler; var addedOptions = deviceCommand.Options.Where(option => existingDc.Options.All(o => o.Name != option.Name)).ToList(); foreach (var option in addedOptions) { existingDc.Options.Add(option); changed = true; } var removedOptions = existingDc.Options.Where(option => deviceCommand.Options.All(o => o.Name != option.Name)).ToList(); foreach (var option in removedOptions) { context.CommandOptions.Local.Remove(option); changed = true; } if (changed) return await context.TrySaveChangesAsync(cancellationToken); return Result.ReportSuccess("Nothing to update"); } }
public async Task RegisterAsyncInvalidDeviceIdTest() { //arrange var dbConnection = new StubIEntityContextConnection { NameOrConnectionStringGet = () => "dcb-RegisterAsyncInvalidDeviceIdTest" }; Database.SetInitializer(new CreateFreshDbInitializer()); var dvb = new DeviceCommandBuilder(dbConnection); var deviceCommand = new DeviceCommand(); //act var result = await dvb.RegisterAsync(3, deviceCommand, CancellationToken.None); //assert Assert.IsTrue(result.HasError); Console.WriteLine(result.Message); }
public async Task RegisterAsyncInvalidDeviceIdTest() { //arrange var dbConnection = new UnitTestDbConnection(); Database.SetInitializer(new CreateFreshDbInitializer()); var dvb = new DeviceCommandBuilder(dbConnection); var deviceCommand = new DeviceCommand(); //act var result = await dvb.RegisterAsync(3, deviceCommand, CancellationToken.None); //assert Assert.IsTrue(result.HasError); Console.WriteLine(result.Message); }
private Task Publish(DeviceType deviceType, Device device, DeviceTypeCommand deviceTypeCommand, DeviceCommand deviceCommand, string argument) { JavaScriptSerializer js = new JavaScriptSerializer(); var o = new { DeviceName = device.Name, DeviceCommandName = (deviceCommand == null ? null : deviceCommand.Name), DeviceTypeCommandName = (deviceTypeCommand == null ? null : deviceTypeCommand.Name), DeviceTypeCommandValue = (deviceTypeCommand == null ? null : deviceTypeCommand.Value), Argument = argument, DeviceTypeName = (device == null || device.Type == null ? null : device.Type.Name), device.CurrentLevelInt, device.CurrentLevelText }; var str = js.Serialize(o); client.Publish(SystemTopic, Encoding.UTF8.GetBytes(str)); return Task.FromResult(0); }
public async Task RegisterAsyncAddedCommandOptionsTest() { //arrange var dbConnection = new StubIEntityContextConnection { NameOrConnectionStringGet = () => "dcb-RegisterAsyncAddedCommandOptionsTest" }; Database.SetInitializer(new CreateFreshDbInitializer()); var dvb = new DeviceCommandBuilder(dbConnection); var device = UnitTesting.CreateFakeDevice(); var deviceCommand = new DeviceCommand { Name = "Unit Testing Command", }; var option1 = new CommandOption { Name = "Option 1" }; var option2 = new CommandOption { Name = "Option 2" }; deviceCommand.Options.Add(option1); deviceCommand.Options.Add(option2); using (var context = new ZvsContext(dbConnection)) { device.Commands.Add(deviceCommand); context.Devices.Add(device); await context.SaveChangesAsync(); } var option3 = new CommandOption { Name = "Option 3" }; deviceCommand.Options.Add(option3); //act var result = await dvb.RegisterAsync(device.Id, deviceCommand, CancellationToken.None); Console.WriteLine(result.Message); List<DeviceCommand> deviceCommands; using (var context = new ZvsContext(dbConnection)) { deviceCommands = await context.DeviceCommands .Include(o => o.Options) .Include(o => o.Device) .Where(o => o.Id == deviceCommand.Id) .ToListAsync(); } //assert Assert.IsFalse(result.HasError, result.Message); Assert.IsTrue(deviceCommands.Count == 1, "Device has an unexpected number of commands"); Assert.IsTrue(deviceCommands[0].Options.Count == 3, "Option not removed as expected"); Assert.IsTrue(deviceCommands[0].Options[2].Name == option3.Name, "Option mismatch"); }
public override Task ProcessDeviceCommandAsync(Device device, DeviceCommand command, string argument, string argument2) { return Publish(device.Type, device, null, command, argument); }
private void AddCommand(int deviceID, string name, ZvsContext context) { context.DeviceCommands.FirstOrDefaultAsync(d => d.Name == name && d.DeviceId == deviceID).ContinueWith( t => { if (motionCommand != null) return; motionCommand = context.DeviceCommands.Add(new DeviceCommand() { DeviceId = deviceID, Description = name, Name = name, UniqueIdentifier = Guid.NewGuid().ToString(), ArgumentType = DataType.STRING, Help = name, CustomData1 = "Value", CustomData2 = name, SortOrder = 0 }); context.TrySaveChangesAsync().ContinueWith(tt => { if (tt.Result.HasError) ZvsEngine.log.Error(tt.Result.Message); }).Wait(); }).Wait(); }
public async Task RunCommandTest() { //Arrange var dbConnection = new UnitTestDbConnection(); Database.SetInitializer(new CreateFreshDbInitializer()); int? commandIdRan = 0; var arg1Ran = ""; var arg2Ran = ""; var commandProcessor = new StubICommandProcessor { RunCommandAsyncNullableOfInt32StringStringCancellationToken = (commandId, argument, argument2, cancellationToken) => { commandIdRan = commandId; arg1Ran = argument; arg2Ran = argument2; return Task.FromResult(Result.ReportSuccess()); } }; var log = new StubIFeedback<LogEntry> { ReportAsyncT0CancellationToken = (e, c) => { Console.WriteLine(e); return Task.FromResult(0); } }; var device0 = UnitTesting.CreateFakeDevice(); var device = UnitTesting.CreateFakeDevice(); using (var context = new ZvsContext(dbConnection)) { var deviceCommand = new DeviceCommand { Name = "Turn On" }; device.Commands.Add(deviceCommand); context.Devices.Add(device0); context.Devices.Add(device); await context.SaveChangesAsync(CancellationToken.None); var cts = new CancellationTokenSource(); var runner = new JavaScriptRunner(log, commandProcessor, dbConnection); var script = $@" function f1() {{ var result = runCommand({deviceCommand.Id },'98', '0'); logInfo(result.Message); }}; f1();"; //Act var result = await runner.ExecuteScriptAsync(script, cts.Token); //Assert Assert.IsFalse(result.HasError, result.Message); Assert.IsTrue(deviceCommand.Id == commandIdRan, "Wrong command ran!"); Assert.IsTrue("98" == arg1Ran, "command argument1 not passed in correctly."); Assert.IsTrue("0" == arg2Ran, "command argument2 not passed in correctly."); } }
public override async Task ProcessDeviceCommandAsync(Device device, DeviceCommand command, string argument, string argument2) { if (!command.UniqueIdentifier.Contains("DYNAMIC_CMD_")) return; var nodeNumber = Convert.ToByte(device.NodeNumber); //Get more info from this Node from OpenZWave var node = GetNode(MHomeId, nodeNumber); if (!IsNodeReady(nodeNumber)) { await Log.ReportInfoFormatAsync(CancellationToken, "Failed to issue command on {0}, node {1}. Node not ready.", device.Name, nodeNumber); return; } switch (command.ArgumentType) { case DataType.BYTE: { byte b; byte.TryParse(argument, out b); var value = node.Values.FirstOrDefault(o => o.ValueID.GetId().ToString(CultureInfo.InvariantCulture).Equals(command.CustomData2)); if (value != null) MManager.SetValue(value.ValueID, b); break; } case DataType.BOOL: { bool b; bool.TryParse(argument, out b); var value = node.Values.FirstOrDefault(o => o.ValueID.GetId().ToString(CultureInfo.InvariantCulture).Equals(command.CustomData2)); if (value != null) MManager.SetValue(value.ValueID, b); break; } case DataType.DECIMAL: { var f = Convert.ToSingle(argument); var value = node.Values.FirstOrDefault(o => o.ValueID.GetId().ToString(CultureInfo.InvariantCulture).Equals(command.CustomData2)); if (value != null) MManager.SetValue(value.ValueID, f); break; } case DataType.LIST: case DataType.STRING: { var value = node.Values.FirstOrDefault(o => o.ValueID.GetId().ToString(CultureInfo.InvariantCulture).Equals(command.CustomData2)); if (value != null) MManager.SetValue(value.ValueID, argument); break; } case DataType.INTEGER: { int i; int.TryParse(argument, out i); var value = node.Values.FirstOrDefault(o => o.ValueID.GetId().ToString(CultureInfo.InvariantCulture).Equals(command.CustomData2)); if (value != null) MManager.SetValue(value.ValueID, i); break; } } }
private async void NotificationHandler() { switch (MNotification.GetType()) { case ZWNotification.Type.NodeProtocolInfo: { #region NodeProtocolInfo var node = GetNode(MNotification.GetHomeId(), MNotification.GetNodeId()); if (node != null) { node.Label = MManager.GetNodeType(MHomeId, node.ID); Debug.WriteLine("[Node Protocol Info] " + node.Label); //Find device type var deviceTypeId = FindDeviceTypeId(node.Label); if (deviceTypeId == UnknownTypeId) await Log.ReportWarningFormatAsync(CancellationToken, "[Unknown Node Label] {0}", node.Label); using (var context = new ZvsContext(EntityContextConnection)) { var ozwDevice = await context.Devices .FirstOrDefaultAsync(d => d.Type.Adapter.AdapterGuid == AdapterGuid && d.NodeNumber == node.ID); //If we don't already have the device if (ozwDevice == null) break; if (ozwDevice.DeviceTypeId != deviceTypeId) { ozwDevice.DeviceTypeId = deviceTypeId; var result = await context.TrySaveChangesAsync(CancellationToken); if (result.HasError) await Log.ReportErrorFormatAsync(CancellationToken, "Failed to change device type. {0}", result.Message); } #region Last Event Value Storage //Node event value placeholder var lastEventResult = await DeviceValueBuilder.RegisterAsync(new DeviceValue { DeviceId = ozwDevice.Id, UniqueIdentifier = LastEventNameValueId, Name = "Last Node Event Value", Genre = "Custom", Index = "0", ValueType = DataType.BYTE, CommandClass = "0", Value = "0", IsReadOnly = true }, ozwDevice, CancellationToken); if (lastEventResult.HasError) await Log.ReportErrorFormatAsync(CancellationToken, "An error occured when registering the last event value. {0}", lastEventResult.Message); #endregion } } break; #endregion } case ZWNotification.Type.ValueAdded: { #region ValueAdded var node = GetNode(MNotification.GetHomeId(), MNotification.GetNodeId()); var vid = MNotification.GetValueID(); var value = new Value { ValueID = vid, Label = MManager.GetValueLabel(vid), Genre = vid.GetGenre().ToString(), Index = vid.GetIndex().ToString(CultureInfo.InvariantCulture), Type = vid.GetType().ToString(), CommandClassID = vid.GetCommandClassId().ToString(CultureInfo.InvariantCulture), Help = MManager.GetValueHelp(vid) }; var readOnly = MManager.IsValueReadOnly(vid); node.AddValue(value); var valueIdString = vid.GetId().ToString(CultureInfo.InvariantCulture); #if DEBUG var sw = new Stopwatch(); sw.Start(); #endif string data; var b = MManager.GetValueAsString(vid, out data); Debug.WriteLine("[ValueAdded] Node: {0}, Label: {1}, Data: {2}, result: {3}", node.ID, value.Label, data, b); using (var context = new ZvsContext(EntityContextConnection)) { var d = await context.Devices.FirstOrDefaultAsync(o => o.Type.Adapter.AdapterGuid == AdapterGuid && o.NodeNumber == node.ID); if (d == null) { await Log.ReportWarningAsync("ValueAdded called on a node id that was not found in the database", CancellationToken); break; } //Values are 'unknown' at this point so don't report a value change. var valueSaveResult = await DeviceValueBuilder.RegisterAsync(new DeviceValue { DeviceId = d.Id, UniqueIdentifier = valueIdString, Name = value.Label, Genre = value.Genre, Index = value.Index, CommandClass = value.CommandClassID, Value = data, ValueType = ConvertType(vid), IsReadOnly = readOnly }, d, CancellationToken); if (valueSaveResult.HasError) await Log.ReportErrorFormatAsync(CancellationToken, "An error occured when registering device value. {0}", valueSaveResult.Message); #region Install Dynamic Commands if (!readOnly) { var argumentType = TranslateDataType(vid.GetType()); var deviceCommand = new DeviceCommand { DeviceId = d.Id, UniqueIdentifier = string.Format("DYNAMIC_CMD_{0}", valueIdString), Name = string.Format("Set {0}", value.Label), ArgumentType = argumentType, Help = string.IsNullOrEmpty(value.Help) ? string.Empty : value.Help, CustomData1 = string.IsNullOrEmpty(value.Label) ? string.Empty : value.Label, CustomData2 = string.IsNullOrEmpty(valueIdString) ? string.Empty : valueIdString, SortOrder = EvaluateOrder(value.Genre) }; //Special case for lists add additional info if (argumentType == DataType.LIST) { //Install the allowed options/values String[] options; if (MManager.GetValueListItems(vid, out options)) foreach (var option in options) deviceCommand.Options.Add(new CommandOption { Name = option }); } var saveDynamicResult = await DeviceCommandBuilder.RegisterAsync(d.Id, deviceCommand, CancellationToken); if (saveDynamicResult.HasError) await Log.ReportErrorFormatAsync(CancellationToken, "An error occured when registering dynamic command. {0}", saveDynamicResult.Message); } #endregion } #if DEBUG sw.Stop(); Debug.WriteLine("Added new Openzwave Value in {0}", sw.Elapsed.ToString() as object); #endif break; #endregion } case ZWNotification.Type.ValueRemoved: { #region ValueRemoved try { var node = GetNode(MNotification.GetHomeId(), MNotification.GetNodeId()); var vid = MNotification.GetValueID(); var val = node.GetValue(vid); Debug.WriteLine("[ValueRemoved] Node:" + node.ID + ",Label:" + MManager.GetValueLabel(vid)); node.RemoveValue(val); //TODO: Remove from values and command table } catch (Exception ex) { Log.ReportErrorFormatAsync(CancellationToken, "Value removed error. {0}", ex.Message).Wait(); } break; #endregion } case ZWNotification.Type.ValueChanged: { #region ValueChanged var node = GetNode(MNotification.GetHomeId(), MNotification.GetNodeId()); var vid = MNotification.GetValueID(); var value = new Value { ValueID = vid, Label = MManager.GetValueLabel(vid), Genre = vid.GetGenre().ToString(), Index = vid.GetIndex().ToString(CultureInfo.InvariantCulture), Type = vid.GetType().ToString(), CommandClassID = vid.GetCommandClassId().ToString(CultureInfo.InvariantCulture), Help = MManager.GetValueHelp(vid) }; var readOnly = MManager.IsValueReadOnly(vid); var data = GetValue(vid); //m_manager.GetValueAsString(vid, out data); Debug.WriteLine("[ValueChanged] Node:" + node.ID + ", Label:" + value.Label + ", Data:" + data); using (var context = new ZvsContext(EntityContextConnection)) { var device = await context.Devices .Include(o => o.Type) .FirstOrDefaultAsync(o => o.Type.Adapter.AdapterGuid == AdapterGuid && o.NodeNumber == node.ID); if (device == null) { await Log.ReportWarningAsync("ValueChanged called on a node id that was not found in the database", CancellationToken); break; } var valueIdString = vid.GetId().ToString(CultureInfo.InvariantCulture); var oldValue = await context.DeviceValues.Where( o => o.DeviceId == device.Id && o.UniqueIdentifier == valueIdString) .Select(o => o.Value).FirstOrDefaultAsync(); if (oldValue != null && oldValue != data) await Log.ReportInfoFormatAsync(CancellationToken, "{0} {1} {2} changed from {3} to {4}", device.Location, device.Name, value.Label, oldValue, data); //Update device value var deviceValueResult = await DeviceValueBuilder.RegisterAsync(new DeviceValue { DeviceId = device.Id, UniqueIdentifier = valueIdString, Name = value.Label, Genre = value.Genre, Index = value.Index, CommandClass = value.CommandClassID, Value = data, ValueType = ConvertType(vid), IsReadOnly = readOnly }, device, CancellationToken); if (deviceValueResult.HasError) await Log.ReportErrorFormatAsync(CancellationToken, "An error occured when updating device values. {0}", deviceValueResult.Message); #region Update Device Status Properties //Update Current Status Field var changed = false; if (device.Type.UniqueIdentifier == OpenzWaveDeviceTypes.Thermostat.ToString()) { if (value.Label == "Temperature") { double level; double.TryParse(data, out level); var levelTxt = string.Format("{0}° F", level); if (!device.CurrentLevelInt.Equals(level)) { device.CurrentLevelInt = level; changed = true; } if (device.CurrentLevelText != levelTxt) { device.CurrentLevelText = levelTxt; changed = true; } } } else if (device.Type.UniqueIdentifier == OpenzWaveDeviceTypes.Switch.ToString()) { if (value.Label == "Basic") { double level; if (double.TryParse(data, out level)) { var levelOnOff = level > 0 ? 100 : 0; var leveltxt = level > 0 ? "On" : "Off"; if (!device.CurrentLevelInt.Equals(levelOnOff)) { device.CurrentLevelInt = levelOnOff; changed = true; } if (device.CurrentLevelText != leveltxt) { device.CurrentLevelText = leveltxt; changed = true; } } } else if (value.Label == "Switch" || value.Label == "Level") //Some Intermatic devices do not set basic when changing status { bool state; if (bool.TryParse(data, out state)) { var levelOnOff = state ? 100 : 0; var leveltxt = state ? "On" : "Off"; if (!device.CurrentLevelInt.Equals(levelOnOff)) { device.CurrentLevelInt = levelOnOff; changed = true; } if (device.CurrentLevelText != leveltxt) { device.CurrentLevelText = leveltxt; changed = true; } } } } else if (device.Type.UniqueIdentifier == OpenzWaveDeviceTypes.Sensor.ToString()) { if (value.Label == "Power") { double watts; if (double.TryParse(data, out watts)) { device.CurrentLevelInt = watts; device.CurrentLevelText = string.Format("{0}W", watts); changed = true; } } } else { if (value.Label == "Basic") { double level; double.TryParse(data, out level); var levelInt = (int)level; var levelTxt = level + "%"; if (!device.CurrentLevelInt.Equals(levelInt)) { device.CurrentLevelInt = levelInt; changed = true; } if (device.CurrentLevelText != levelTxt) { device.CurrentLevelText = levelTxt; changed = true; } } } if (changed) { var result = await context.TrySaveChangesAsync(CancellationToken); if (result.HasError) await Log.ReportErrorFormatAsync(CancellationToken, "Failed update device level. {0}", result.Message); } #endregion #region Update Device Commands if (!readOnly) { var uid = string.Format("DYNAMIC_CMD_{0}", valueIdString); var deviceCommand = await context.DeviceCommands.FirstOrDefaultAsync(o => o.DeviceId == device.Id && o.UniqueIdentifier == uid); if (deviceCommand != null) { //User commands are more important so lets see them first in the GUIs int order; switch (value.Genre) { case "Basic": order = 4; break; case "User": order = 3; break; case "Config": order = 2; break; default: order = 1; break; } //After Value is Added, Value Name other values properties can change so update. deviceCommand.Name = "Set " + value.Label; deviceCommand.Help = value.Help; deviceCommand.CustomData1 = value.Label; deviceCommand.SortOrder = order; var result = await context.TrySaveChangesAsync(CancellationToken); if (result.HasError) await Log.ReportErrorFormatAsync(CancellationToken, "Failed to update device command. {0}", result.Message); } } #endregion #region Repoll Dimmers //Some dimmers take x number of seconds to dim to desired level. Therefore the level received here initially is a //level between old level and new level. (if going from 0 to 100 we get 84 here). //To get the real level re-poll the device a second or two after a level change was received. bool enableDimmerRepoll = bool.TryParse(await device.GetDeviceSettingAsync(OpenzWaveDeviceTypeSettings.EnableRepollOnLevelChange.ToString(), context), out enableDimmerRepoll) && enableDimmerRepoll; if (InitialPollingComplete && enableDimmerRepoll && device.Type.UniqueIdentifier == OpenzWaveDeviceTypes.Dimmer.ToString() && value.Label == "Basic") { //only allow each device to re-poll 1 time. if (!_nodeValuesRepolling.Contains(device.NodeNumber)) { _nodeValuesRepolling.Add(device.NodeNumber); await Task.Delay(3500); MManager.RefreshValue(vid); Debug.WriteLine("Node {0} value re-polled", device.NodeNumber); //Do not allow another re-poll for 10 seconds await Task.Delay(10000); _nodeValuesRepolling.Remove(device.NodeNumber); } } #endregion } break; #endregion } case ZWNotification.Type.Group: { #region Group Debug.WriteLine("[Group]"); break; #endregion } case ZWNotification.Type.NodeAdded: { #region NodeAdded // if this node was in zwcfg*.xml, this is the first node notification // if not, the NodeNew notification should already have been received //if (GetNode(m_notification.GetHomeId(), m_notification.GetNodeId()) == null) //{ var node = new Node { ID = MNotification.GetNodeId(), HomeID = MNotification.GetHomeId() }; _mNodeList.Add(node); Debug.WriteLine("[NodeAdded] ID:" + node.ID + " Added"); await AddNewDeviceToDatabase(node.ID); break; #endregion } case ZWNotification.Type.NodeNew: { #region NodeNew // Add the new node to our list (and flag as uninitialized) var node = new Node { ID = MNotification.GetNodeId(), HomeID = MNotification.GetHomeId() }; _mNodeList.Add(node); Debug.WriteLine("[NodeNew] ID:" + node.ID + " Added"); await AddNewDeviceToDatabase(node.ID); break; #endregion } case ZWNotification.Type.NodeRemoved: { #region NodeRemoved foreach (var node in _mNodeList.Where(node => node.ID == MNotification.GetNodeId())) { Debug.WriteLine("[NodeRemoved] ID:" + node.ID); _mNodeList.Remove(node); break; } break; #endregion } case ZWNotification.Type.NodeNaming: { #region NodeNaming const string manufacturerNameValueId = "MN1"; const string productNameValueId = "PN1"; const string nodeLocationValueId = "NL1"; const string nodeNameValueId = "NN1"; var node = GetNode(MNotification.GetHomeId(), MNotification.GetNodeId()); if (node != null) { node.Manufacturer = MManager.GetNodeManufacturerName(MHomeId, node.ID); node.Product = MManager.GetNodeProductName(MHomeId, node.ID); node.Location = MManager.GetNodeLocation(MHomeId, node.ID); node.Name = MManager.GetNodeName(MHomeId, node.ID); Debug.WriteLine("[NodeNaming] Node:" + node.ID + ", Product:" + node.Product + ", Manufacturer:" + node.Manufacturer + ")"); using (var context = new ZvsContext(EntityContextConnection)) { var device = await context.Devices.FirstOrDefaultAsync(o => o.Type.Adapter.AdapterGuid == AdapterGuid && o.NodeNumber == node.ID); if (device == null) { await Log.ReportWarningAsync("NodeNaming called on a node id that was not found in the database", CancellationToken); break; } //lets store the manufacturer name and product name in the values table. //Giving ManufacturerName a random value_id 9999058723211334120 var mNameResult = await DeviceValueBuilder.RegisterAsync(new DeviceValue { DeviceId = device.Id, UniqueIdentifier = manufacturerNameValueId, Name = "Manufacturer Name", Genre = "Custom", Index = "0", ValueType = DataType.STRING, CommandClass = "0", Value = node.Manufacturer, IsReadOnly = true }, device, CancellationToken); if (mNameResult.HasError) await Log.ReportErrorFormatAsync(CancellationToken, "An error occured when updating manufacturing name value. {0}", mNameResult.Message); var productNameResult = await DeviceValueBuilder.RegisterAsync(new DeviceValue { DeviceId = device.Id, UniqueIdentifier = productNameValueId, Name = "Product Name", Genre = "Custom", Index = "0", ValueType = DataType.STRING, CommandClass = "0", Value = node.Product, IsReadOnly = true }, device, CancellationToken); if (productNameResult.HasError) await Log.ReportErrorFormatAsync(CancellationToken, "An error occured when updating product name value. {0}", productNameResult.Message); var nodeResult = await DeviceValueBuilder.RegisterAsync(new DeviceValue { DeviceId = device.Id, UniqueIdentifier = nodeLocationValueId, Name = "Node Location", Genre = "Custom", Index = "0", ValueType = DataType.STRING, CommandClass = "0", Value = node.Location, IsReadOnly = true }, device, CancellationToken); if (nodeResult.HasError) await Log.ReportErrorFormatAsync(CancellationToken, "An error occured when updating node location value. {0}", nodeResult.Message); var nodeNameResult = await DeviceValueBuilder.RegisterAsync(new DeviceValue { DeviceId = device.Id, UniqueIdentifier = nodeNameValueId, Name = "Node Name", Genre = "Custom", Index = "0", ValueType = DataType.STRING, CommandClass = "0", Value = node.Name, IsReadOnly = true }, device, CancellationToken); if (nodeNameResult.HasError) await Log.ReportErrorFormatAsync(CancellationToken, "An error occured when updating node name value. {0}", nodeNameResult.Message); } } break; #endregion } case ZWNotification.Type.NodeEvent: { #region NodeEvent var node = GetNode(MNotification.GetHomeId(), MNotification.GetNodeId()); var gevent = MNotification.GetEvent(); if (node == null) break; await Log.ReportInfoFormatAsync(CancellationToken, "[NodeEvent] Node: {0}, Event Byte: {1}", node.ID, gevent); using (var context = new ZvsContext(EntityContextConnection)) { var device = await context.Devices .FirstOrDefaultAsync(o => o.Type.Adapter.AdapterGuid == AdapterGuid && o.NodeNumber == node.ID); if (device == null) { await Log.ReportWarningAsync("NodeNaming called on a node id that was not found in the database", CancellationToken); break; } var dv = await context.DeviceValues.FirstOrDefaultAsync(o => o.DeviceId == device.Id && o.UniqueIdentifier == LastEventNameValueId); //Node event value placeholder if (dv == null) break; dv.Value = gevent.ToString(CultureInfo.InvariantCulture); var result = await context.TrySaveChangesAsync(CancellationToken); if (result.HasError) await Log.ReportErrorFormatAsync(CancellationToken, "Failed to update device value. {0}", result.Message); //Since open wave events are differently than values changes, we need to fire the value change event every time we receive the //event regardless if it is the same value or not. //TODO: //dv.DeviceValueDataChanged(new DeviceValue.ValueDataChangedEventArgs(dv.Id, dv.Value, string.Empty)); } break; #endregion } case ZWNotification.Type.DriverReady: { #region DriverReady _nodesReady.Clear(); MHomeId = MNotification.GetHomeId(); await Log.ReportInfoFormatAsync(CancellationToken, "Initializing...driver with Home ID 0x{0} is ready.", MHomeId.ToString("X8")); break; #endregion } case ZWNotification.Type.NodeQueriesComplete: { #region NodeQueriesComplete var node = GetNode(MNotification.GetHomeId(), MNotification.GetNodeId()); if (node != null) { await Log.ReportInfoFormatAsync(CancellationToken, "Initializing...node {0} queries complete", node.ID); if (!_nodesReady.Contains(node.ID)) _nodesReady.Add(node.ID); //await UpdateLastHeardFrom(node.ID); } break; #endregion } case ZWNotification.Type.EssentialNodeQueriesComplete: { #region EssentialNodeQueriesComplete var node = GetNode(MNotification.GetHomeId(), MNotification.GetNodeId()); if (node != null) { await Log.ReportInfoFormatAsync(CancellationToken, "Initializing...node {0} essential queries complete", node.ID); if (!_nodesReady.Contains(node.ID)) _nodesReady.Add(node.ID); //await UpdateLastHeardFrom(node.ID); } break; #endregion } case ZWNotification.Type.AllNodesQueried: { #region AllNodesQueried //This is an important message to see. It tells you that you can start issuing commands await Log.ReportInfoAsync("Ready: All nodes queried", CancellationToken); InitialPollingComplete = true; MManager.WriteConfig(MNotification.GetHomeId()); await EnablePollingOnDevices(); break; #endregion } case ZWNotification.Type.AllNodesQueriedSomeDead: { #region AllNodesQueriedSomeDead //This is an important message to see. It tells you that you can start issuing commands await Log.ReportInfoAsync("Ready: All nodes queried but some are dead.", CancellationToken); InitialPollingComplete = true; MManager.WriteConfig(MNotification.GetHomeId()); await EnablePollingOnDevices(); break; #endregion } case ZWNotification.Type.AwakeNodesQueried: { #region AwakeNodesQueried await Log.ReportInfoAsync("Ready: Awake nodes queried (but not some sleeping nodes)", CancellationToken); InitialPollingComplete = true; MManager.WriteConfig(MNotification.GetHomeId()); await EnablePollingOnDevices(); break; #endregion } case ZWNotification.Type.PollingDisabled: { #region PollingDisabled await Log.ReportInfoAsync("Polling disabled notification", CancellationToken); break; #endregion } case ZWNotification.Type.PollingEnabled: { #region PollingEnabled await Log.ReportInfoAsync("Polling enabled notification", CancellationToken); break; #endregion } case ZWNotification.Type.SceneEvent: { #region SceneEvent await Log.ReportInfoAsync("Scene event notification received", CancellationToken); break; #endregion } } }
public async Task RunCommandAsyncDeviceCommand() { //Arrange var dbConnection = new UnitTestDbConnection(); Database.SetInitializer(new CreateFreshDbInitializer()); var adapterManager = new StubIAdapterManager { FindZvsAdapterGuid = adapterGuid => new StubZvsAdapter { IsEnabled = true, ProcessDeviceCommandAsyncDeviceDeviceCommandStringString = (adapterDevice, command, argument, argument2) => Task.FromResult(0) } }; var log = new StubIFeedback<LogEntry>(); var cts = new CancellationTokenSource(); var commmandProcessor = new CommandProcessor(adapterManager, dbConnection, log); var device = UnitTesting.CreateFakeDevice(); using (var context = new ZvsContext(dbConnection)) { var deviceCommand = new DeviceCommand { Name = "Turn On" }; device.Commands.Add(deviceCommand); context.Devices.Add(device); await context.SaveChangesAsync(CancellationToken.None); //Act var result = await commmandProcessor.RunCommandAsync(deviceCommand.Id, "", "", cts.Token); Console.WriteLine(result.Message); //Assert Assert.IsFalse(result.HasError); } }
public async Task ExecuteDeviceCommandAsyncAdapterNotLoadedTest() { //Arrange var dbConnection = new UnitTestDbConnection(); Database.SetInitializer(new CreateFreshDbInitializer()); var adapterManager = new StubIAdapterManager { FindZvsAdapterGuid = adapterGuid => null }; var ranstoredCommands = new List<int>(); var log = new StubIFeedback<LogEntry>(); var cts = new CancellationTokenSource(); var commmandProcessor = new CommandProcessor(adapterManager, dbConnection, log); var device = UnitTesting.CreateFakeDevice(); using (var context = new ZvsContext(dbConnection)) { var deviceCommand = new DeviceCommand { Name = "Turn On" }; device.Commands.Add(deviceCommand); context.Devices.Add(device); await context.SaveChangesAsync(CancellationToken.None); //Act var result = await commmandProcessor.ExecuteDeviceCommandAsync(deviceCommand, "1", "", cts.Token); Console.WriteLine(result.Message); //Assert Assert.IsTrue(result.HasError); Assert.IsTrue(ranstoredCommands.Count == 0, "Process did not run the correct amount of commands."); Assert.IsTrue(result.Message.Contains("not loaded"), "Expect error message to contain 'not loaded'"); } }
public async Task ExecuteBuiltinCommandAsyncSceneTest() { //Arrange var dbConnection = new UnitTestDbConnection(); Database.SetInitializer(new CreateFreshDbInitializer()); var deviceCommandIds = new List<int>(); var adapterManager = new StubIAdapterManager { FindZvsAdapterGuid = adapterGuid => new StubZvsAdapter { IsEnabled = true, ProcessDeviceCommandAsyncDeviceDeviceCommandStringString = async (adapterDevice, command, argument, argument2) => deviceCommandIds.Add(command.Id) } }; var log = new StubIFeedback<LogEntry> { ReportAsyncT0CancellationToken = (e, c) => { Console.WriteLine(e); return Task.FromResult(0); } }; var cts = new CancellationTokenSource(); var commmandProcessor = new CommandProcessor(adapterManager, dbConnection, log); var device = UnitTesting.CreateFakeDevice(); using (var context = new ZvsContext(dbConnection)) { var deviceCommand = new DeviceCommand { Name = "Turn On" }; device.Commands.Add(deviceCommand); context.Devices.Add(device); var scene = new Scene { Name = "Test Scene" }; scene.Commands.Add(new SceneStoredCommand { Command = deviceCommand, Argument = "0" }); context.Scenes.Add(scene); var builtinCommand = new BuiltinCommand { Name = "Activate Scene", UniqueIdentifier = "RUN_SCENE" }; context.Commands.Add(builtinCommand); await context.SaveChangesAsync(new CancellationToken()); //Act var result = await commmandProcessor.ExecuteBuiltinCommandAsync(builtinCommand, scene.Id.ToString(CultureInfo.InvariantCulture), "", cts.Token); Console.WriteLine(result.Message); //Assert Assert.IsFalse(result.HasError); Assert.IsTrue(deviceCommandIds.Count == 1, "Process did not run the correct amount of commands."); Assert.IsTrue(deviceCommand.Id == deviceCommandIds[0], "Ran the wrong scene!"); } }
public async Task ExecuteDeviceCommandAsyncOkTest() { //Arrange var dbConnection = new UnitTestDbConnection(); Database.SetInitializer(new CreateFreshDbInitializer()); var commandsSendToAdapter = new List<int>(); var adapterManager = new StubIAdapterManager { FindZvsAdapterGuid = adapterGuid => new StubZvsAdapter { IsEnabled = true, ProcessDeviceCommandAsyncDeviceDeviceCommandStringString = (adapterDevice, command, argument, argument2) => { commandsSendToAdapter.Add(command.Id); return Task.FromResult(0); } } }; var log = new StubIFeedback<LogEntry>(); var cts = new CancellationTokenSource(); var commmandProcessor = new CommandProcessor(adapterManager, dbConnection, log); var device = UnitTesting.CreateFakeDevice(); using (var context = new ZvsContext(dbConnection)) { var deviceCommand = new DeviceCommand { Name = "Turn On" }; device.Commands.Add(deviceCommand); context.Devices.Add(device); await context.SaveChangesAsync(CancellationToken.None); //Act var result = await commmandProcessor.ExecuteDeviceCommandAsync(deviceCommand, "1", "", cts.Token); Console.WriteLine(result.Message); //Assert Assert.IsFalse(result.HasError); Assert.IsTrue(commandsSendToAdapter.Count == 1, "Process did not run the correct amount of commands."); Assert.IsTrue(commandsSendToAdapter[0] == deviceCommand.Id, "Wrong command processed"); } }
public async Task RegisterAsyncAddNewCommandTest() { //arrange var dbConnection = new StubIEntityContextConnection { NameOrConnectionStringGet = () => "dcb-RegisterAsyncAddNewCommandTest" }; Database.SetInitializer(new CreateFreshDbInitializer()); var dvb = new DeviceCommandBuilder( dbConnection); var device = UnitTesting.CreateFakeDevice(); using (var context = new ZvsContext(dbConnection)) { context.Devices.Add(device); await context.SaveChangesAsync(); } var deviceCommand = new DeviceCommand() { Name = "Unit Testing Command" }; //act var result = await dvb.RegisterAsync(device.Id, deviceCommand, CancellationToken.None); Console.WriteLine(result.Message); Device d; using (var context = new ZvsContext(dbConnection)) { d = await context.Devices .Include(o=> o.Commands) .FirstOrDefaultAsync(o => o.Id == device.Id); } //assert Assert.IsFalse(result.HasError, result.Message); Assert.IsNotNull(d, "device not found!"); Assert.IsTrue(d.Commands.Count == 1, "Device has an unexpected number of commands"); Assert.IsTrue(d.Commands[0].Name == deviceCommand.Name, "Device command did not save correctly"); }
public override Task ProcessDeviceCommandAsync(Device device, DeviceCommand command, string argument, string argument2) { return Task.FromResult(0); }
public override Task ProcessDeviceCommandAsync(Device device, DeviceCommand command, string argument, string argument2) { throw new NotImplementedException(); }
public abstract Task ProcessDeviceCommandAsync(Device device, DeviceCommand command, string argument, string argument2);