private void NotificationHandler()
        {
            //osae.AddToLog("Notification: " + m_notification.GetType().ToString(), false);
            switch (m_notification.GetType())
            {
                case ZWNotification.Type.ValueAdded:
                    {
                        Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId());
                        using (zvsEntities2 db = new zvsEntities2(zvsEntityControl.GetzvsConnectionString))
                        {
                            device d = GetDevices(db).FirstOrDefault(o => o.node_id == node.ID);
                            if (d != null)
                            {
                                ZWValueID vid = m_notification.GetValueID();
                                Value value = new Value();
                                value.ValueID = vid;
                                value.Label = m_manager.GetValueLabel(vid);
                                value.Genre = vid.GetGenre().ToString();
                                value.Index = vid.GetIndex().ToString();
                                value.Type = vid.GetType().ToString();
                                value.CommandClassID = vid.GetCommandClassId().ToString();
                                value.Help = m_manager.GetValueHelp(vid);
                                bool read_only = m_manager.IsValueReadOnly(vid);
                                node.AddValue(value);

                                string data = "";
                                bool b = m_manager.GetValueAsString(vid, out data);

                                WriteToLog(Urgency.INFO, "[ValueAdded] Node:" + node.ID + ", Label:" + value.Label + ", Data:" + data + ", result: " + b.ToString());

                                //Values are 'unknown' at this point so dont report a value change.
                                DefineOrUpdateDeviceValue(new device_values
                                {
                                    device_id = d.id,
                                    value_id = vid.GetId().ToString(),
                                    label_name = value.Label,
                                    genre = value.Genre,
                                    index = value.Index,
                                    type = value.Type,
                                    commandClassId = value.CommandClassID,
                                    value = data,
                                    read_only = read_only
                                }, true);

                                #region Install Dynamic Commands

                                if (!read_only)
                                {
                                    Data_Types pType = Data_Types.NONE;

                                    //Set param types for command
                                    switch (vid.GetType())
                                    {
                                        case ZWValueID.ValueType.List:
                                            pType = Data_Types.LIST;
                                            break;
                                        case ZWValueID.ValueType.Byte:
                                            pType = Data_Types.BYTE;
                                            break;
                                        case ZWValueID.ValueType.Decimal:
                                            pType = Data_Types.DECIMAL;
                                            break;
                                        case ZWValueID.ValueType.Int:
                                            pType = Data_Types.INTEGER;
                                            break;
                                        case ZWValueID.ValueType.String:
                                            pType = Data_Types.STRING;
                                            break;
                                        case ZWValueID.ValueType.Short:
                                            pType = Data_Types.SHORT;
                                            break;
                                        case ZWValueID.ValueType.Bool:
                                            pType = Data_Types.BOOL;
                                            break;
                                    }

                                    //Install the Node Specific Command
                                    int order;
                                    switch (value.Genre)
                                    {
                                        case "User":
                                            order = 1;
                                            break;
                                        case "Config":
                                            order = 2;
                                            break;
                                        default:
                                            order = 99;
                                            break;
                                    }

                                    device_commands dynamic_dc = new device_commands
                                    {
                                        device_id = d.id,
                                        name = "DYNAMIC_CMD_" + value.Label.ToUpper(),
                                        friendly_name = "Set " + value.Label,
                                        arg_data_type = (int)pType,
                                        help = value.Help,
                                        custom_data1 = value.Label,
                                        custom_data2 = vid.GetId().ToString(),
                                        sort_order = order
                                    };

                                    //Special case for lists add additional info
                                    if (vid.GetType() == ZWValueID.ValueType.List)
                                    {
                                        //Install the allowed options/values
                                        String[] options;
                                        if (m_manager.GetValueListItems(vid, out options))
                                            foreach (string option in options)
                                                dynamic_dc.device_command_options.Add(new device_command_options { name = option });
                                    }

                                    DefineOrUpdateDeviceCommand(dynamic_dc);
                                }
                                #endregion
                            }
                        }
                        break;
                    }

                case ZWNotification.Type.ValueRemoved:
                    {
                        try
                        {
                            Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId());
                            ZWValueID vid = m_notification.GetValueID();
                            Value val = node.GetValue(vid);

                            WriteToLog(Urgency.INFO, "[ValueRemoved] Node:" + node.ID + ",Label:" + m_manager.GetValueLabel(vid));

                            node.RemoveValue(val);
                            //TODO: Remove from values and command table
                        }
                        catch (Exception ex)
                        {
                            WriteToLog(Urgency.ERROR, "ValueRemoved error: " + ex.Message);
                        }
                        break;
                    }

                case ZWNotification.Type.ValueChanged:
                    {
                        //try
                        //{
                            Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId());
                            ZWValueID vid = m_notification.GetValueID();
                            Value value = new Value();
                            value.ValueID = vid;
                            value.Label = m_manager.GetValueLabel(vid);
                            value.Genre = vid.GetGenre().ToString();
                            value.Index = vid.GetIndex().ToString();
                            value.Type = vid.GetType().ToString();
                            value.CommandClassID = vid.GetCommandClassId().ToString();
                            value.Help = m_manager.GetValueHelp(vid);
                            bool read_only = m_manager.IsValueReadOnly(vid);

                            string data = GetValue(vid);
                            //m_manager.GetValueAsString(vid, out data);

                            WriteToLog(Urgency.INFO,"[ValueChanged] Node:" + node.ID + ", Label:" + value.Label + ", Data:" + data);
                            using (zvsEntities2 db = new zvsEntities2(zvsEntityControl.GetzvsConnectionString))
                            {
                                device d = GetDevices(db).FirstOrDefault(o => o.node_id == node.ID);

                                if (d != null)
                                {
                                   // d.last_heard_from = DateTime.Now;
                                    //db.SaveChanges();

                                    //Update Device Commands
                                   if (!read_only)
                                    {
                                        //User commands are more important so lets see them first in the GUIs
                                        int order;
                                        switch (value.Genre)
                                        {
                                            case "User":
                                                order = 1;
                                                break;
                                            case "Config":
                                                order = 2;
                                                break;
                                            default:
                                                order = 99;
                                                break;
                                        }

                                        device_commands dc = d.device_commands.FirstOrDefault(c => c.custom_data2 == vid.GetId().ToString());

                                        if (dc != null)
                                        {
                                            //After Value is Added, Value Name other value properties can change so update.
                                            dc.friendly_name = "Set " + value.Label;
                                            dc.help = value.Help;
                                            dc.custom_data1 = value.Label;
                                            dc.sort_order = order;
                                        }
                                    }

                                    //Some dimmers take x number of seconds to dim to desired level.  Therefor the level recieved 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 repoll the device a second or two after a level change was recieved.
                                    bool EnableDimmerRepoll = false;
                                    bool.TryParse(device_property_values.GetDevicePropertyValue(d.id, "ENABLEREPOLLONLEVELCHANGE"), out EnableDimmerRepoll);

                                    if (FinishedInitialPoll && EnableDimmerRepoll)
                                    {
                                        switch (node.Label)
                                        {
                                            case "Multilevel Switch":
                                            case "Multilevel Power Switch":
                                                {

                                                    switch (value.Label)
                                                    {
                                                        case "Basic":
                                                            device_values dv_basic = d.device_values.FirstOrDefault(v => v.value_id == vid.GetId().ToString());
                                                            if (dv_basic != null)
                                                            {
                                                                string prevVal = dv_basic.value;
                                                                //If it is truely new
                                                                if (!prevVal.Equals(data))
                                                                {
                                                                    System.Timers.Timer t = new System.Timers.Timer();
                                                                    t.Interval = 5000;
                                                                    t.Elapsed += (sender, e) =>
                                                                    {
                                                                        m_manager.RefreshNodeInfo(m_homeId, (byte)d.node_id);
                                                                        t.Enabled = false;
                                                                    };
                                                                    t.Enabled = true;
                                                                }
                                                            }
                                                            break;
                                                    }
                                                    break;
                                                }
                                        }
                                    }

                                    DefineOrUpdateDeviceValue(new device_values
                                    {
                                        device_id = d.id,
                                        value_id = vid.GetId().ToString(),
                                        label_name = value.Label,
                                        genre = value.Genre,
                                        index = value.Index,
                                        type = value.Type,
                                        commandClassId = value.CommandClassID,
                                        value = data,
                                        read_only = read_only
                                    });
                                }
                                else
                                {
                                    WriteToLog(Urgency.WARNING, "Getting changes on an unknown device!");
                                }

                            }
                        //}
                        //catch (Exception ex)
                        //{
                        //    WriteToLog(Urgency.ERROR, "error: " + ex.Message);
                        //}
                        break;
                    }

                case ZWNotification.Type.Group:
                    {
                        WriteToLog(Urgency.INFO, "[Group]"); ;
                        break;
                    }

                case ZWNotification.Type.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)
                        //{
                            Node node = new Node();
                            node.ID = m_notification.GetNodeId();
                            node.HomeID = m_notification.GetHomeId();
                            m_nodeList.Add(node);

                            WriteToLog(Urgency.INFO, "[NodeAdded] ID:" + node.ID.ToString() + " Added");
                        //}
                        break;
                    }

                case ZWNotification.Type.NodeNew:
                    {
                        // Add the new node to our list (and flag as uninitialized)
                        Node node = new Node();
                        node.ID = m_notification.GetNodeId();
                        node.HomeID = m_notification.GetHomeId();
                        m_nodeList.Add(node);

                        WriteToLog(Urgency.INFO, "[NodeNew] ID:" + node.ID.ToString() + " Added");
                        break;
                    }

                case ZWNotification.Type.NodeRemoved:
                    {
                        foreach (Node node in m_nodeList)
                        {
                            if (node.ID == m_notification.GetNodeId())
                            {
                                WriteToLog(Urgency.INFO, "[NodeRemoved] ID:" + node.ID.ToString());
                                m_nodeList.Remove(node);
                                break;
                            }
                        }
                        break;
                    }

                case ZWNotification.Type.NodeProtocolInfo:
                    {
                        using (zvsEntities2 db = new zvsEntities2(zvsEntityControl.GetzvsConnectionString))
                        {
                            Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId());
                            if (node != null)
                            {
                                node.Label = m_manager.GetNodeType(m_homeId, node.ID);
                            }
                            string deviceName = "UNKNOWN";
                            device_types device_type = null;

                            if (node != null)
                            {
                                WriteToLog(Urgency.INFO, "[Node Protocol Info] " + node.Label);

                                switch (node.Label)
                                {
                                    case "Toggle Switch":
                                    case "Binary Toggle Switch":
                                    case "Binary Switch":
                                    case "Binary Power Switch":
                                    case "Binary Scene Switch":
                                    case "Binary Toggle Remote Switch":
                                        deviceName = "OpenZWave Switch " + node.ID;
                                        device_type = GetDeviceType("SWITCH", db);
                                        break;
                                    case "Multilevel Toggle Remote Switch":
                                    case "Multilevel Remote Switch":
                                    case "Multilevel Toggle Switch":
                                    case "Multilevel Switch":
                                    case "Multilevel Power Switch":
                                    case "Multilevel Scene Switch":
                                        deviceName = "OpenZWave Dimmer " + node.ID;
                                        device_type = GetDeviceType("DIMMER", db);
                                        break;
                                    case "Multiposition Motor":
                                    case "Motor Control Class A":
                                    case "Motor Control Class B":
                                    case "Motor Control Class C":
                                        deviceName = "Variable Motor Control " + node.ID;
                                        device_type = GetDeviceType("DIMMER", db);
                                        break;
                                    case "General Thermostat V2":
                                    case "Heating Thermostat":
                                    case "General Thermostat":
                                    case "Setback Schedule Thermostat":
                                    case "Setpoint Thermostat":
                                    case "Setback Thermostat":
                                    case "Thermostat":
                                        deviceName = "OpenZWave Thermostat " + node.ID;
                                        device_type = GetDeviceType("THERMOSTAT", db);
                                        break;
                                    case "Static PC Controller":
                                    case "Static Controller":
                                    case "Portable Remote Controller":
                                    case "Portable Installer Tool":
                                    case "Static Scene Controller":
                                    case "Static Installer Tool":
                                        deviceName = "OpenZWave Controller " + node.ID;
                                        device_type = GetDeviceType("CONTROLLER", db);
                                        break;
                                    case "Secure Keypad Door Lock":
                                    case "Advanced Door Lock":
                                    case "Door Lock":
                                    case "Entry Control":
                                        deviceName = "OpenZWave Door Lock " + node.ID;
                                        device_type = GetDeviceType("DOORLOCK", db);
                                        break;
                                    case "Alarm Sensor":
                                    case "Basic Routing Alarm Sensor":
                                    case "Routing Alarm Sensor":
                                    case "Basic Zensor Alarm Sensor":
                                    case "Zensor Alarm Sensor":
                                    case "Advanced Zensor Alarm Sensor":
                                    case "Basic Routing Smoke Sensor":
                                    case "Routing Smoke Sensor":
                                    case "Basic Zensor Smoke Sensor":
                                    case "Zensor Smoke Sensor":
                                    case "Advanced Zensor Smoke Sensor":
                                    case "Routing Binary Sensor":
                                    case "Routing Multilevel Sensor":
                                        deviceName = "OpenZWave Sensor " + node.ID;
                                        device_type = GetDeviceType("SENSOR", db);
                                        break;
                                    default:
                                        {
                                            WriteToLog(Urgency.INFO, "[Node Label] " + node.Label);
                                            break;
                                        }
                                }
                                if (device_type != null)
                                {

                                    device ozw_device = GetDevices(db).FirstOrDefault(d => d.node_id == node.ID);
                                    //If we dont already have the device
                                    if (ozw_device == null)
                                    {
                                        ozw_device = new device
                                        {
                                            node_id = node.ID,
                                            device_types = device_type,
                                            friendly_name = deviceName
                                        };

                                        db.devices.AddObject(ozw_device);
                                        db.SaveChanges();

                                        ozw_device.CallAdded(new EventArgs());
                                    }

                                    #region Last Event Value Storeage
                                    //Node event value placeholder
                                    DefineOrUpdateDeviceValue(new device_values
                                    {
                                        device_id = ozw_device.id,
                                        value_id = LaastEventNameValueId,
                                        label_name = "Last Node Event Value",
                                        genre = "Custom",
                                        index = "0",
                                        type = "Byte",
                                        commandClassId = "0",
                                        value = "0",
                                        read_only = true
                                    });

                                    #endregion
                                }
                                else
                                    WriteToLog(Urgency.WARNING, string.Format("Found unknown device '{0}', node #{1}!", node.Label, node.ID));

                            }
                        }
                        break;
                    }

                case ZWNotification.Type.NodeNaming:
                    {
                        string ManufacturerNameValueId = "9999058723211334120";
                        string ProductNameValueId = "9999058723211334121";
                        string NodeLocationValueId = "9999058723211334122";
                        string NodeNameValueId = "9999058723211334123";

                        using (zvsEntities2 db = new zvsEntities2(zvsEntityControl.GetzvsConnectionString))
                {

                        Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId());
                        if (node != null)
                        {
                            node.Manufacturer = m_manager.GetNodeManufacturerName(m_homeId, node.ID);
                            node.Product = m_manager.GetNodeProductName(m_homeId, node.ID);
                            node.Location = m_manager.GetNodeLocation(m_homeId, node.ID);
                            node.Name = m_manager.GetNodeName(m_homeId, node.ID);

                            device d = GetDevices(db).FirstOrDefault(o => o.node_id == node.ID);
                            if (d != null)
                            {
                                //lets store the manufacturer name and product name in the values table.
                                //Giving ManufacturerName a random value_id 9999058723211334120
                                DefineOrUpdateDeviceValue(new device_values
                                {
                                    device_id = d.id,
                                    value_id = ManufacturerNameValueId,
                                    label_name = "Manufacturer Name",
                                    genre = "Custom",
                                    index = "0",
                                    type = "String",
                                    commandClassId = "0",
                                    value = node.Manufacturer,
                                    read_only = true
                                });
                                DefineOrUpdateDeviceValue(new device_values
                                {
                                    device_id = d.id,
                                    value_id = ProductNameValueId,
                                    label_name = "Product Name",
                                    genre = "Custom",
                                    index = "0",
                                    type = "String",
                                    commandClassId = "0",
                                    value = node.Product,
                                    read_only = true
                                });
                                DefineOrUpdateDeviceValue(new device_values
                                {
                                    device_id = d.id,
                                    value_id = NodeLocationValueId,
                                    label_name = "Node Location",
                                    genre = "Custom",
                                    index = "0",
                                    type = "String",
                                    commandClassId = "0",
                                    value = node.Location,
                                    read_only = true
                                });
                                DefineOrUpdateDeviceValue(new device_values
                                {
                                    device_id = d.id,
                                    value_id = NodeNameValueId,
                                    label_name = "Node Name",
                                    genre = "Custom",
                                    index = "0",
                                    type = "String",
                                    commandClassId = "0",
                                    value = node.Name,
                                    read_only = true
                                });
                            }
                        }
                        WriteToLog(Urgency.INFO, "[NodeNaming] Node:" + node.ID + ", Product:" + node.Product + ", Manufacturer:" + node.Manufacturer + ")");
                        }
                        break;
                    }

                case ZWNotification.Type.NodeEvent:
                    {
                        Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId());
                        byte gevent = m_notification.GetEvent();

                        if (node != null)
                        {
                            WriteToLog(Urgency.INFO, string.Format("[NodeEvent] Node: {0}, Event Byte: {1}", node.ID, gevent));

                            using (zvsEntities2 db = new zvsEntities2(zvsEntityControl.GetzvsConnectionString))
                            {
                                #region Last Event Value Storeage
                                device d = GetDevices(db).FirstOrDefault(o => o.node_id == node.ID);
                                if (d != null)
                                {
                                    //Node event value placeholder
                                    device_values dv = d.device_values.FirstOrDefault(v => v.value_id == LaastEventNameValueId);
                                    if (dv != null)
                                    {
                                        dv.value = gevent.ToString();
                                        db.SaveChanges();

                                        //Since events are differently than values fire the value change event every time we recieve the event regardless if
                                        //it is the same value or not.
                                        dv.DeviceValueDataChanged(new device_values.ValueDataChangedEventArgs { device_value_id  = dv.id, previousValue = string.Empty});
                                    }
                                }
                                #endregion
                            }
                        }
                        break;

                    }

                case ZWNotification.Type.PollingDisabled:
                    {
                        Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId());

                        if (node != null)
                        {
                            WriteToLog(Urgency.INFO, "[PollingDisabled] Node:" + node.ID);
                        }

                        break;
                    }

                case ZWNotification.Type.PollingEnabled:
                    {
                        Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId());

                        if (node != null)
                        {
                            WriteToLog(Urgency.INFO, "[PollingEnabled] Node:" + node.ID);
                        }
                        break;
                    }

                case ZWNotification.Type.DriverReady:
                    {
                        m_homeId = m_notification.GetHomeId();
                        WriteToLog(Urgency.INFO, "Initializing: Driver with Home ID 0x" + m_homeId);
                        WriteToLog(Urgency.INFO, "[DriverReady] Initializing...driver with Home ID 0x" + m_homeId);
                        break;
                    }

                case ZWNotification.Type.NodeQueriesComplete:
                    {

                        Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId());

                        if (node != null)
                        {
                            using (zvsEntities2 db = new zvsEntities2(zvsEntityControl.GetzvsConnectionString))
                            {
                                device d = GetDevices(db).FirstOrDefault(o => o.node_id == node.ID);
                                if (d != null)
                                {
                                    d.last_heard_from = DateTime.Now;
                                }
                                db.SaveChanges();

                                zvsEntityControl.CallDeviceModified(d, "last_heard_from");
                            }

                            WriteToLog(Urgency.INFO, "Initializing: Node " + node.ID + " query complete.");
                            WriteToLog(Urgency.INFO, "[NodeQueriesComplete] Initializing...node " + node.ID + " query complete.");
                        }

                        break;
                    }

                case ZWNotification.Type.AllNodesQueried:
                    {
                        using (zvsEntities2 db = new zvsEntities2(zvsEntityControl.GetzvsConnectionString))
                        {
                            foreach (Node n in m_nodeList)
                            {
                                device d = GetDevices(db).FirstOrDefault(o => o.node_id == n.ID);

                                if (d != null)
                                {
                                    if (device_property_values.GetDevicePropertyValue(d.id, "ENABLEPOLLING").ToUpper().Equals("TRUE"))
                                        EnablePolling(n.ID);
                                }
                            }
                        }

                        WriteToLog(Urgency.INFO, "Ready:  All nodes queried. Plug-in now ready.");
                        IsReady = true;

                        FinishedInitialPoll = true;
                        break;
                    }

                case ZWNotification.Type.AwakeNodesQueried:
                    {
                        using (zvsEntities2 db = new zvsEntities2(zvsEntityControl.GetzvsConnectionString))
                        {
                            foreach (Node n in m_nodeList)
                            {
                                device d = GetDevices(db).FirstOrDefault(o => o.node_id == n.ID);

                                if (d != null)
                                {
                                    if (device_property_values.GetDevicePropertyValue(d.id, "ENABLEPOLLING").ToUpper().Equals("TRUE"))
                                        EnablePolling(n.ID);
                                }
                            }
                        }

                        WriteToLog(Urgency.INFO, "Ready:  Awake nodes queried (but not some sleeping nodes).");
                        IsReady = true;

                        FinishedInitialPoll = true;

                        break;
                    }
            }
        }
示例#2
0
 public void AddValue(Value val)
 {
     m_values.Add(val);
 }
示例#3
0
 public void RemoveValue(Value val)
 {
     m_values.Remove(val);
 }
        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
                    }
            }
        }