private void Events()
        {
            if (_devices != null)
            {
                Logger.Log(LogMsgType.INFO, "Events started!", LogAuthor.Adapter);
                foreach (var device in _devices)
                {
                    if (device.Events == null)
                    {
                        continue;
                    }
                    if (device.Properties == null)
                    {
                        string json_response = clp_connection.GetCLPObject(clp_user, CLPtokenToString(), device.AUID);

                        CLP_Parameters clp_parameters = new CLP_Parameters();
                        clp_parameters.Parse(json_response);
                        device.Properties = clp_parameters.GetParams(device.AUID);
                    }
                    Thread thread = new Thread(() => EventCheck(device));
                    thread.IsBackground = true;
                    thread.Start();
                    _eventThreads?.Add(thread);
                }
            }
        }
        private bool ArePropertiesSet(CLP_Connection clp_connection, string clp_user, string clp_token, string clp_auid, Dictionary <string, string> props)
        {
            string json_response = clp_connection.GetCLPObject(clp_user, clp_token, clp_auid);

            CLP_Parameters clp_parameters = new CLP_Parameters();

            clp_parameters.Parse(json_response);
            Dictionary <string, string> dict = clp_parameters.GetParams(clp_auid);


            foreach (KeyValuePair <string, string> item in props)
            {
                if (!dict.ContainsKey(item.Key))
                {
                    return(false);
                }

                if (!dict[item.Key].ToUpper().Equals(item.Value.ToUpper()))
                {
                    return(false);
                }
            }


            return(true);
        }
        private void VicinityWCFService_OnRequestReceived(object sender, HTTPRequestEventArgs e)
        {
            if (e.clp_params_request)
            {
                string json_response = clp_connection.GetCLPObject(clp_user, CLPtokenToString(), e.AUID);

                CLP_Parameters clp_parameters = new CLP_Parameters();
                clp_parameters.Parse(json_response);
                e.clp_params = clp_parameters.GetParams(e.AUID);

                Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] requested parameters from CLP!", LogAuthor.Adapter);
            }
            else
            {
                switch (e.action_type)
                {
                case RequestActionType.OVEN_DELAYED_BAKING:
                {
                    if (e.clp_params.ContainsKey("duration") &&
                        e.clp_params.ContainsKey("delay") &&
                        e.clp_params.ContainsKey("temperature") &&
                        e.clp_params.ContainsKey("heater_system"))
                    {
                        try
                        {
                            int duration    = Convert.ToInt32(e.clp_params["duration"]);
                            int delay       = Convert.ToInt32(e.clp_params["delay"]);
                            int temperature = Convert.ToInt32(e.clp_params["temperature"]);


                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Oven_POST_DelayedBaking(clp_connection, clp_user, CLPtokenToString(), e.AUID, duration, delay, temperature, e.clp_params["heater_system"].ToUpper());
                                });


                            e.action_executed = true;


                            string logtext = "";
                            foreach (KeyValuePair <string, string> item in e.clp_params)
                            {
                                if (!String.IsNullOrEmpty(logtext))
                                {
                                    logtext += "; ";
                                }

                                logtext += item.Key + " = " + item.Value;
                            }

                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: delayed_baking -> " + logtext, LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.OVEN_BAKING:
                {
                    if (e.clp_params.ContainsKey("duration") &&
                        e.clp_params.ContainsKey("temperature") &&
                        e.clp_params.ContainsKey("heater_system"))
                    {
                        try
                        {
                            int duration    = Convert.ToInt32(e.clp_params["duration"]);
                            int temperature = Convert.ToInt32(e.clp_params["temperature"]);


                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Oven_POST_Baking(clp_connection, clp_user, CLPtokenToString(), e.AUID, duration, temperature, e.clp_params["heater_system"].ToUpper());
                                });


                            e.action_executed = true;


                            string logtext = "";
                            foreach (KeyValuePair <string, string> item in e.clp_params)
                            {
                                if (!String.IsNullOrEmpty(logtext))
                                {
                                    logtext += "; ";
                                }

                                logtext += item.Key + " = " + item.Value;
                            }

                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: baking -> " + logtext, LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.OVEN_LIGHT:
                {
                    if (e.clp_params.ContainsKey("light"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Oven_PUT_Light(clp_connection, clp_user, CLPtokenToString(), e.AUID, e.clp_params["light"].ToUpper());
                                });


                            e.action_executed = true;


                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: light -> " + e.clp_params["light"], LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.OVEN_CHILD_LOCK:
                {
                    if (e.clp_params.ContainsKey("child_lock"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Oven_PUT_ChildLock(clp_connection, clp_user, CLPtokenToString(), e.AUID, e.clp_params["child_lock"].ToUpper());
                                });


                            e.action_executed = true;


                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: child lock -> " + e.clp_params["child_lock"], LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.OVEN_BAKING_START:
                {
                    try
                    {
                        Task.Factory.StartNew(() =>
                            {
                                app_methods.Oven_POST_ActionStart(clp_connection, clp_user, CLPtokenToString(), e.AUID);
                            });

                        e.action_executed = true;

                        Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: start baking ", LogAuthor.Adapter);
                    }
                    catch (Exception ex)
                    {
                        exception?.Invoke(ex);

                        e.action_executed = false;
                    }
                }
                break;

                case RequestActionType.OVEN_BAKING_STOP:
                {
                    try
                    {
                        Task.Factory.StartNew(() =>
                            {
                                app_methods.Oven_POST_ActionStop(clp_connection, clp_user, CLPtokenToString(), e.AUID);
                            });


                        e.action_executed = true;

                        Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: stop baking ", LogAuthor.Adapter);
                    }
                    catch (Exception ex)
                    {
                        exception?.Invoke(ex);

                        e.action_executed = false;
                    }
                }
                break;

                case RequestActionType.OVEN_HEATER_SYSTEM:
                {
                    if (e.clp_params.ContainsKey("heater_system_sub"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Oven_PUT_HeaterSystem(clp_connection, clp_user, CLPtokenToString(), e.AUID, e.clp_params["heater_system_sub"].ToUpper());
                                });


                            e.action_executed = true;

                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: heater system -> " + e.clp_params["heater_system_sub"].ToUpper(), LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.OVEN_SET_MEAT_PROBE_TEMPERATURE:
                {
                    if (e.clp_params.ContainsKey("set_meat_probe_temp"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Oven_PUT_SetMeatProbeTemp(clp_connection, clp_user, CLPtokenToString(), e.AUID, Int32.Parse(e.clp_params["set_meat_probe_temp"]));
                                });


                            e.action_executed = true;

                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: set meat probe temp -> " + e.clp_params["set_meat_probe_temp"].ToUpper(), LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.OVEN_SET_BAKING_TEMPERATURE:
                {
                    if (e.clp_params.ContainsKey("set_oven_temperature"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Oven_PUT_SetBakingTemp(clp_connection, clp_user, CLPtokenToString(), e.AUID, Int32.Parse(e.clp_params["set_oven_temperature"]));
                                });


                            e.action_executed = true;

                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: set baking temp -> " + e.clp_params["set_oven_temperature"].ToUpper(), LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.OVEN_SET_BAKING_TIME:
                {
                    if (e.clp_params.ContainsKey("set_bake_time_minutes"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Oven_PUT_SetBakingTime(clp_connection, clp_user, CLPtokenToString(), e.AUID, Int32.Parse(e.clp_params["set_bake_time_minutes"]));
                                });


                            e.action_executed = true;

                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: set baking time -> " + e.clp_params["set_bake_time_minutes"].ToUpper(), LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.OVEN_ALARM_TIME:
                {
                    if (e.clp_params.ContainsKey("alarm_time_minutes"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Oven_PUT_AlarmTime(clp_connection, clp_user, CLPtokenToString(), e.AUID, Int32.Parse(e.clp_params["alarm_time_minutes"]));
                                });


                            e.action_executed = true;

                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: alarm time -> " + e.clp_params["alarm_time_minutes"].ToUpper(), LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.OVEN_BAKING_START_TIME_HOUR:
                {
                    if (e.clp_params.ContainsKey("baking_start_time_hour"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Oven_PUT_BakingStartTimeHour(clp_connection, clp_user, CLPtokenToString(), e.AUID, Int32.Parse(e.clp_params["baking_start_time_hour"]));
                                });


                            e.action_executed = true;

                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: baking start time hour -> " + e.clp_params["baking_start_time_hour"].ToUpper(), LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.OVEN_BAKING_START_TIME_MINUTE:
                {
                    if (e.clp_params.ContainsKey("baking_start_time_minute"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Oven_PUT_BakingStartTimeMinute(clp_connection, clp_user, CLPtokenToString(), e.AUID, Int32.Parse(e.clp_params["baking_start_time_minute"]));
                                });


                            e.action_executed = true;

                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: baking start time minute -> " + e.clp_params["baking_start_time_minute"].ToUpper(), LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                //refrigerator
                case RequestActionType.REFRIGERATOR_CHILD_LOCK:
                {
                    if (e.clp_params.ContainsKey("child_lock"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Refrigerator_PUT_ChildLock(clp_connection, clp_user, CLPtokenToString(), e.AUID, e.clp_params["child_lock"].ToUpper());
                                });


                            e.action_executed = true;


                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: child lock -> " + e.clp_params["child_lock"], LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.REFRIGERATOR_TEMPERATURE:
                {
                    if (e.clp_params.ContainsKey("refrigerator_temperature"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Refrigerator_PUT_RefrigeratorTemp(clp_connection, clp_user, CLPtokenToString(), e.AUID, Int32.Parse(e.clp_params["refrigerator_temperature"]));
                                });


                            e.action_executed = true;


                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: refrigerator temperature -> " + e.clp_params["refrigerator_temperature"], LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.REFRIGERATOR_FREEZER_TEMPERATURE:
                {
                    if (e.clp_params.ContainsKey("freezer_temperature"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Refrigerator_PUT_FreezerTemp(clp_connection, clp_user, CLPtokenToString(), e.AUID, Int32.Parse(e.clp_params["freezer_temperature"]));
                                });


                            e.action_executed = true;


                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: freezer temperature -> " + e.clp_params["freezer_temperature"], LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.REFRIGERATOR_FASTFREEZE:
                {
                    if (e.clp_params.ContainsKey("fastfreeze"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Refrigerator_PUT_Fastfreeze(clp_connection, clp_user, CLPtokenToString(), e.AUID, e.clp_params["fastfreeze"].ToUpper());
                                });


                            e.action_executed = true;


                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: fastfreeze -> " + e.clp_params["fastfreeze"], LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;

                case RequestActionType.REFRIGERATOR_SUPERCOOL:
                {
                    if (e.clp_params.ContainsKey("supercool"))
                    {
                        try
                        {
                            Task.Factory.StartNew(() =>
                                {
                                    app_methods.Refrigerator_PUT_Supercool(clp_connection, clp_user, CLPtokenToString(), e.AUID, e.clp_params["supercool"].ToUpper());
                                });


                            e.action_executed = true;


                            Logger.Log(LogMsgType.INFO, "[" + e.AUID + "] action: supercool -> " + e.clp_params["supercool"], LogAuthor.Adapter);
                        }
                        catch (Exception ex)
                        {
                            exception?.Invoke(ex);

                            e.action_executed = false;
                        }
                    }
                }
                break;
                }
            }
        }
        private void EventCheck(Device device)
        {
            CookingStatus cookingStatus = CookingStatus.None;

            while (true)
            {
                try
                {
                    if (clp_connection != null && device.Properties != null && device.Events != null && device.Properties.Count > 0 && device.Events.Count > 0)
                    {
                        string json_response = clp_connection.GetCLPObject(clp_user, CLPtokenToString(), device.AUID);

                        CLP_Parameters clp_parameters = new CLP_Parameters();
                        clp_parameters.Parse(json_response);
                        Dictionary <string, string> props = clp_parameters.GetParams(device.AUID);

                        if (props != null)
                        {
                            foreach (var item in device.Events)
                            {
                                if (props.ContainsKey(item.CLPID) && device.Properties.ContainsKey(item.CLPID) &&
                                    !device.Properties[item.CLPID].ToUpper().Equals(props[item.CLPID].ToUpper()))
                                {
                                    //property value has changed
                                    //publish event
                                    device.Properties[item.CLPID] = props[item.CLPID];
                                    string value = props[item.CLPID].ToUpper();

                                    PublishEvent(item.EID, device.OID, device.AUID, item.CLPID, value);

                                    if (item.EID.Equals("device_status") && (value.Equals("IDLE")))
                                    {
                                        cookingStatus = CookingStatus.None;
                                        ChangeActionStatus(device.OID, device.AUID);
                                    }
                                    else if ((item.EID.Equals("refrigerator_door") || item.EID.Equals("freezer_door") || item.EID.Equals("door")) &&
                                             value.Equals("OPENED"))
                                    {
                                        item.LastChanged    = DateTime.Now;
                                        item.EmergencyStage = EmergencyStage.None;
                                        if (cookingStatus == CookingStatus.BakingFinished)
                                        {
                                            cookingStatus = CookingStatus.None;
                                        }
                                    }
                                    else if (item.EID.Equals("device_status") && (value.Equals("RUNNING")))
                                    {
                                        cookingStatus = CookingStatus.Baking;
                                    }
                                }
                                else if (item.EmergencyLevel != null && item.LastChanged.Year >= 2018 && item.EmergencyStage != EmergencyStage.Three &&
                                         ((device.DeviceType == DeviceType.refrigerator && device.Properties[item.CLPID].ToUpper().Equals("OPENED")) ||
                                          (device.DeviceType == DeviceType.oven && device.Properties[item.CLPID].ToUpper().Equals("CLOSED") && cookingStatus == CookingStatus.BakingFinished)))
                                {
                                    DateTime now = DateTime.Now;
                                    foreach (var level in item.EmergencyLevel)
                                    {
                                        int index = item.EmergencyLevel.IndexOf(level);
                                        if ((now - item.LastChanged).TotalMinutes >= level.Min && index == (int)item.EmergencyStage)
                                        {
                                            int    lvl     = (int)level.Stage;
                                            string eventID = null;
                                            if (device.DeviceType == DeviceType.oven)
                                            {
                                                eventID = "oven_emergency";
                                            }
                                            else
                                            {
                                                if (item.EID.Contains("refrigerator"))
                                                {
                                                    eventID = "refrigerator_emergency";
                                                }
                                                else
                                                {
                                                    eventID = "freezer_emergency";
                                                }
                                            }

                                            PublishEvent(eventID, device.OID, device.AUID, eventID, lvl.ToString());

                                            item.EmergencyStage = (EmergencyStage)(index + 1);
                                            break;
                                        }
                                    }
                                }
                                else if (cookingStatus == CookingStatus.Baking &&
                                         item.EID.Equals("device_status") && device.Properties[item.CLPID].ToUpper().Equals("RUNNING") &&
                                         props["BAKE_REMAINING_TIME_MINUTES"].Equals("0") && props["BAKE_REMAINING_TIME_SECONDS"].Equals("0"))
                                {
                                    cookingStatus = CookingStatus.BakingFinished;

                                    foreach (var evnt in device.Events)
                                    {
                                        if (evnt.EID.Equals("door"))
                                        {
                                            evnt.LastChanged    = DateTime.Now;
                                            evnt.EmergencyStage = EmergencyStage.None;
                                            break;
                                        }
                                    }

                                    PublishEvent(item.EID, device.OID, device.AUID, item.CLPID, "AFTER_BAKE");
                                }
                            }
                        }
                    }
                    Thread.Sleep(1000);
                }
                catch (Exception e)
                {
                    Logger.Log(LogMsgType.ERROR, "Device: " + device.OID + " " + e.ToString(), LogAuthor.Event);
                }
            }
        }