/// <summary> /// Run this instance. /// </summary> public void Run() { ConsoleOutputLogger.WriteLine("Starting Automated Sensor Check."); TimeSpan temp = new TimeSpan(); while (!_Shutdown) { try { // check... foreach (string SensorName in SensorCache.Keys) { temp = new TimeSpan(DateTime.Now.Ticks - SensorCache[SensorName].Ticks); if (temp.TotalMinutes > hacs.Properties.Settings.Default.AutomatedSensorCheck_ResponseTimeWindow) { if (!SensorCheckIgnoreConfiguration.SensorCheckIgnoreList.Contains(SensorName)) { ConsoleOutputLogger.WriteLine("#WARNING# An outdated sensor was detected: " + SensorName); } } } } catch (Exception) { } Thread.Sleep(Properties.Settings.Default.SensorCheckIntervalSec * 1000); // just check every 6 seconds... } }
private void PowerOn(ScriptingTimerElement ScriptingTimer) { ScriptingTimer.LastTimeSwitchedOn = DateTime.Now; ScriptingTimer.LastTimeSwitchedOff = DateTime.MinValue; // TODO: Power-On Code ConsoleOutputLogger.WriteLine("Power On " + ScriptingTimer.SwitchName + " by Timer " + ScriptingTimer.TimerName); }
// this is the ELV MAX! Cube monitoring script public void Run() { ConsoleOutputLogger.WriteLine("Starting up SolarLog data gathering..."); while (running) { SolarLogDataSet data = SolarLogDataHelper.UpdateSolarLog(URL, ConsoleOutputLogger); if (data != null) { if (LastDataSet == null) { LastDataSet = data; iQueue.Enqueue(data); } else { bool QueueIt = false; if (data.Pac != LastDataSet.Pac) { QueueIt = true; } if (data.aPdc != LastDataSet.aPdc) { QueueIt = true; } // if the last data set is older than 5 minutes, definitly queue this one... TimeSpan Diff = DateTime.Now - LastDataSet.DateAndTime; //if (Diff.TotalMinutes > Properties.Settings.Default.AutomatedSensorCheck_ResponseTimeWindow) if (Diff.TotalMinutes > 5) { QueueIt = true; } if (QueueIt) { iQueue.Enqueue(data); LastDataSet = data; } } } Thread.Sleep(SolarLogUpdateTime); } }
public static SolarLogDataSet UpdateSolarLog(String URL, ConsoleOutputLogger COL) { SolarLogDataSet Output = new SolarLogDataSet();; // create a web client and get the data String fullURL = "http://" + URL + "/min_cur.js?nocache"; WebClient client = new WebClient(); try { String SolarLogValue = client.DownloadString(fullURL); // hurray, we got a string! // let's parse it! String[] LbL = SolarLogValue.Replace("\r", "").Split(new char[] { '\n' }); foreach (String _line in LbL) { #region Pac if (_line.StartsWith("var Pac=")) { Output.Pac = Convert.ToInt32(_line.Replace("var Pac=", "")); } #endregion #region aPdc if (_line.StartsWith("var aPdc=")) { String firstpart_removed = _line.Replace("var aPdc=new Array(", ""); Output.aPdc = Convert.ToInt32(firstpart_removed.Remove(firstpart_removed.IndexOf(','))); } #endregion } } catch (Exception e) { COL.WriteLine("SolarLog Exception: " + e.Message); return(null); } return(Output); }
public static SolarLogDataSet UpdateSolarLog(String URL, ConsoleOutputLogger COL) { SolarLogDataSet Output = new SolarLogDataSet();; // create a web client and get the data String fullURL = "http://"+URL+"/min_cur.js?nocache"; WebClient client = new WebClient (); try { String SolarLogValue = client.DownloadString(fullURL); // hurray, we got a string! // let's parse it! String[] LbL = SolarLogValue.Replace("\r","").Split(new char[] {'\n'}); foreach(String _line in LbL) { #region Pac if (_line.StartsWith("var Pac=")) { Output.Pac = Convert.ToInt32(_line.Replace("var Pac=","")); } #endregion #region aPdc if (_line.StartsWith("var aPdc=")) { String firstpart_removed = _line.Replace("var aPdc=new Array(",""); Output.aPdc = Convert.ToInt32( firstpart_removed.Remove(firstpart_removed.IndexOf(','))); } #endregion } } catch(Exception e) { COL.WriteLine("SolarLog Exception: "+e.Message); return null; } return Output; }
public void Run() { // initialize XS1 Configuration XS1_Configuration = new XS1Configuration(ConfigurationCacheMinutes); MAXMonitoringThread ELVMax = null; SolarLogMonitoringThread SolarLog = null; // Start Sensor-Check Thread SensorCheck Sensorcheck = new SensorCheck(ConsoleOutputLogger); Thread SensorCheckThread = new Thread(new ThreadStart(Sensorcheck.Run)); SensorCheckThread.Start(); // Start Actor Re-Switching Thread ActorReswitching ActorReSwitch_ = new ActorReswitching(XS1_Configuration, ConsoleOutputLogger, TemporaryBlacklist, OnWaitOffLIst); Thread ActorReswitchThread = new Thread(new ThreadStart(ActorReSwitch_.Run)); ActorReswitchThread.Start(); // Start the SolarLog Thread (if enabled) // TODO: make it switchable / configurable if (Properties.Settings.Default.SolarLogEnabled) { SolarLog = new SolarLogMonitoringThread(Properties.Settings.Default.SolarLogURLDomain, ConsoleOutputLogger, SolarLog_DataQueue, Properties.Settings.Default.SolarLogUpdateIntervalMsec); Thread SolarLogThread = new Thread(new ThreadStart(SolarLog.Run)); SolarLogThread.Start(); } // Start the ELVMax Thread if (Properties.Settings.Default.ELVMAXEnabled) { ELVMax = new MAXMonitoringThread(Properties.Settings.Default.ELVMAXIP, Properties.Settings.Default.ELVMAXPort, ConsoleOutputLogger, MAX_DataQueue, Properties.Settings.Default.ELVMAXUpdateIntervalMsec); Thread ELVMaxThread = new Thread(new ThreadStart(ELVMax.Run)); ELVMaxThread.Start(); } XS1MonitoringThread XS1 = new XS1MonitoringThread(ServerName, ConsoleOutputLogger, UserName, Password, XS1_DataQueue); Thread XS1Thread = new Thread(new ThreadStart(XS1.Run)); XS1Thread.Start(); // Start integrated HTTP Server HttpServer httpServer = new HttpServer(Properties.Settings.Default.HTTPPort, Properties.Settings.Default.HTTPIP, Properties.Settings.Default.HTTPDocumentRoot, sensor_data_store, miataru_data_store, XS1_Configuration, ConsoleOutputLogger, ELVMax, Properties.Settings.Default.HTTPAuthEnabled, Properties.Settings.Default.HTTPAuthUsername, Properties.Settings.Default.HTTPAuthPassword, Properties.Settings.Default.HTTPAuthDisabledAdressStartsWith); Thread http_server_thread = new Thread(new ThreadStart(httpServer.listen)); http_server_thread.Start(); // Start Service Monitorng thread if (Properties.Settings.Default.NetworkMonitorEnabled) { NetworkMonitoring monitor = new NetworkMonitoring(ConsoleOutputLogger, NetworkMonitor_Queue, Properties.Settings.Default.NetworkMonitorUpdateIntervalMsec); Thread monitorThread = new Thread(new ThreadStart(monitor.Run)); monitorThread.Start(); } // Start Alarming thread if (Properties.Settings.Default.AlarmingEnabled) { AlarmingThread alarmThread = new AlarmingThread(ConsoleOutputLogger, Alarming_Queue, sensor_data_store, actor_data_store, miataru_data_store); Thread alarming_thread = new Thread(new ThreadStart(alarmThread.Run)); alarming_thread.Start(); } // Start Miataru Thread if (Properties.Settings.Default.MiataruEnabled) { MiataruThread miataruThread = new MiataruThread(ConsoleOutputLogger, miataru_data_store, Properties.Settings.Default.MiataruUpdateTime); Thread miataru_Thread = new Thread(new ThreadStart(miataruThread.Run)); miataru_Thread.Start(); } // Start MQTT Thread if (Properties.Settings.Default.MQTTBindingEnabled) { MQTT_Binding = new MQTT_Handling(ConsoleOutputLogger); Thread mqtt_Thread = new Thread(new ThreadStart(MQTT_Binding.Run)); mqtt_Thread.Start(); } while (!Shutdown) { try { #region Handle XS1 events XS1_DataObject dataobject = null; if (XS1_DataQueue.TryDequeue(out dataobject)) { if (dataobject.Type == ObjectTypes.Actor) { // Write to Disk lock (actor_data_store) { actor_data_store.Write(dataobject.Serialize()); } lock (KnownActorStates.KnownActorStatuses) { bool usethisactor = true; // check if this actor is on temporary blacklist (like when it was handled) lock (TemporaryBlacklist) { if (TemporaryBlacklist.Contains(dataobject.Name)) { usethisactor = false; } TemporaryBlacklist.Remove(dataobject.Name); } if (usethisactor) { // if Alarming is enabled, queue this XS1 Event up for alarming... if (Properties.Settings.Default.AlarmingEnabled) { Alarming_Queue.Enqueue(dataobject); } // this actor action did not result in any action hacs made - so we try to make the best out of it #region Scripting Handling // check if this sensor is something we should act uppon foreach (ScriptingActorElement Element in ScriptingActorConfiguration.ScriptingActorActions) { if (dataobject.Name == Element.SensorToWatchName) { if (dataobject.Value == Element.SensorValue) { // obviously there is a ScriptingActorConfiguration entry // so we execute the actor preset set_state_actuator.set_state_actuator ssa = new set_state_actuator.set_state_actuator(); ConsoleOutputLogger.WriteLineToScreenOnly("detected actor scripting action on actor " + Element.SensorToWatchName + " - " + Element.ActorToSwitchName + " to " + Element.ActionToRunName); if (Element.isCurrentlyWithinStartEndHours()) { #region Scripting Actor Actions if (Element.ActionToRunName == actor_status.URL) { ConsoleOutputLogger.WriteLine("Scripting Actor URL"); // handle URLs -> the ActorToSwitch Name will be the URL to trigger try { WebClient client = new WebClient(); client.Encoding = System.Text.Encoding.UTF8; String JSONInput = client.DownloadString(Element.ActorToSwitchName); ConsoleOutputLogger.WriteLine("Doing HTTP GET on: " + Element.ActorToSwitchName); } catch (Exception e) { ConsoleOutputLogger.WriteLine("Exception on URL Actor Scripting: " + e.Message); } } // check what action is going to happen now... if (Element.ActionToRunName == actor_status.On) { ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, Element.ActorToSwitchName, "ON", XS1_Configuration); } if (Element.ActionToRunName == actor_status.Off) { ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, Element.ActorToSwitchName, "OFF", XS1_Configuration); // remove from OnWaitOffList lock (OnWaitOffLIst) { if (OnWaitOffLIst.Contains(Element.ActorToSwitchName)) { OnWaitOffLIst.Remove(Element.ActorToSwitchName); } } } if (Element.ActionToRunName == actor_status.OnOff) { // look for the current status in the known actors table lock (KnownActorStates.KnownActorStatuses) { if (KnownActorStates.KnownActorStatuses.ContainsKey(Element.ActorToSwitchName)) { current_actor_status Status = KnownActorStates.KnownActorStatuses[Element.ActorToSwitchName]; if (Status.Status == actor_status.On) { ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, Element.ActorToSwitchName, "OFF", XS1_Configuration); } else if (Status.Status == actor_status.Off) { ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, Element.ActorToSwitchName, "ON", XS1_Configuration); } } else { ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, Element.ActorToSwitchName, "ON", XS1_Configuration); } } } if (Element.ActionToRunName == actor_status.OnWaitOff) { lock (OnWaitOffLIst) { ConsoleOutputLogger.WriteLine("Adding " + Element.ActorToSwitchName + " to ActorReSwitching OnWaitOff List"); OnWaitOffLIst.Add(Element.ActorToSwitchName); } ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, Element.ActorToSwitchName, "ON_WAIT_OFF", XS1_Configuration); } #endregion } } } } #endregion #region MQTT Handling Actor if (Properties.Settings.Default.MQTTBindingEnabled) { MQTT_Binding.MQTT_Handle_Actor(dataobject); } #endregion if (KnownActorStates.KnownActorStatuses.ContainsKey(dataobject.Name)) { // is contained if (dataobject.Value == 100) { KnownActorStates.KnownActorStatuses[dataobject.Name] = new current_actor_status(dataobject.Name, actor_status.On); } else { KnownActorStates.KnownActorStatuses[dataobject.Name] = new current_actor_status(dataobject.Name, actor_status.Off); } } else { if (dataobject.Value == 100) { KnownActorStates.KnownActorStatuses.Add(dataobject.Name, new current_actor_status(dataobject.Name, actor_status.On)); } else { KnownActorStates.KnownActorStatuses.Add(dataobject.Name, new current_actor_status(dataobject.Name, actor_status.Off)); } } } else { ConsoleOutputLogger.WriteLine("Actor " + dataobject.Name + " is on the blacklist (ActorReSwitching) and therefore is ignored this time."); } } } else if (dataobject.Type == ObjectTypes.Sensor) { lock (sensor_data_store) { sensor_data_store.Write(dataobject.Serialize()); } // update the sensor in the sensor check Sensorcheck.UpdateSensor(dataobject.Name); // if Alarming is enabled, queue this XS1 Event up for alarming... if (Properties.Settings.Default.AlarmingEnabled) { if (!dataobject.IgnoreForAlarming) // this if for those events which get re-queued as xs1 events despite being for example elvmax events { Alarming_Queue.Enqueue(dataobject); } } #region Scripting // check if this sensor is something we should act uppon foreach (ScriptingActorElement Element in ScriptingActorConfiguration.ScriptingActorActions) { if (dataobject.Name == Element.SensorToWatchName) { if (dataobject.Value == Element.SensorValue) { // obviously there is a ScriptingActorConfiguration entry // so we execute the actor preset set_state_actuator.set_state_actuator ssa = new set_state_actuator.set_state_actuator(); ConsoleOutputLogger.WriteLineToScreenOnly("detected actor scripting action on sensor " + Element.SensorToWatchName + " - " + Element.ActorToSwitchName + " to " + Element.ActionToRunName); if (Element.isCurrentlyWithinStartEndHours()) { #region Scripting Actor actions if (Element.ActionToRunName == actor_status.URL) { ConsoleOutputLogger.WriteLine("Scripting Actor URL"); // handle URLs -> the ActorToSwitch Name will be the URL to trigger try { WebClient client = new WebClient(); client.Encoding = System.Text.Encoding.UTF8; String JSONInput = client.DownloadString(Element.ActorToSwitchName); ConsoleOutputLogger.WriteLine("Doing HTTP GET on: " + Element.ActorToSwitchName); } catch (Exception e) { ConsoleOutputLogger.WriteLine("Exception on URL Actor Scripting: " + e.Message); } } // check what action is going to happen now... if (Element.ActionToRunName == actor_status.On) { ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, Element.ActorToSwitchName, "ON", XS1_Configuration); } if (Element.ActionToRunName == actor_status.Off) { ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, Element.ActorToSwitchName, "OFF", XS1_Configuration); // remove from OnWaitOffList lock (OnWaitOffLIst) { if (OnWaitOffLIst.Contains(Element.ActorToSwitchName)) { OnWaitOffLIst.Remove(Element.ActorToSwitchName); } } } if (Element.ActionToRunName == actor_status.OnOff) { // look for the current status in the known actors table lock (KnownActorStates.KnownActorStatuses) { if (KnownActorStates.KnownActorStatuses.ContainsKey(Element.ActorToSwitchName)) { current_actor_status Status = KnownActorStates.KnownActorStatuses[Element.ActorToSwitchName]; if (Status.Status == actor_status.On) { ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, Element.ActorToSwitchName, "OFF", XS1_Configuration); } else if (Status.Status == actor_status.Off) { ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, Element.ActorToSwitchName, "ON", XS1_Configuration); } } else { ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, Element.ActorToSwitchName, "ON", XS1_Configuration); } } } if (Element.ActionToRunName == actor_status.OnWaitOff) { lock (OnWaitOffLIst) { ConsoleOutputLogger.WriteLine("Adding " + Element.ActorToSwitchName + " to ActorReSwitching OnWaitOff List"); OnWaitOffLIst.Add(Element.ActorToSwitchName); } ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, Element.ActorToSwitchName, "ON_WAIT_OFF", XS1_Configuration); } #endregion } else { ConsoleOutputLogger.WriteLine("Actorswitching Action not triggered since it's out of timespan. (" + Element.StartHour + "-" + Element.EndHour + ")"); } } } } #endregion #region MQTT Handling Sensor if (Properties.Settings.Default.MQTTBindingEnabled) { MQTT_Binding.MQTT_Handle_Sensor(dataobject); } #endregion } else if (dataobject.Type == ObjectTypes.Unknown) { unknown_data_store.Write(dataobject.Serialize()); } ConsoleOutputLogger.WriteLine(ServerName + " - " + dataobject.OriginalXS1Statement); } #endregion #region Handle MAX events // the strategy for MAX events is quite easy: emulate XS1 events and stuff the XS1 queue with those faked events // that takes care of the storage and the if (Properties.Settings.Default.ELVMAXEnabled) { IDeviceDiffSet max_dataobject = null; if (MAX_DataQueue.TryDequeue(out max_dataobject)) { // if Alarming is enabled, queue this ELV MAX up for alarming... if (Properties.Settings.Default.AlarmingEnabled) { Alarming_Queue.Enqueue(max_dataobject); } StringBuilder sb = new StringBuilder(); sb.Append("S\t" + max_dataobject.DeviceName + "\t" + max_dataobject.DeviceType); if (max_dataobject.DeviceType == DeviceTypes.HeatingThermostat) { HeatingThermostatDiff _heating = (HeatingThermostatDiff)max_dataobject; // this is what is different on the heating thermostats //ConsoleOutputLogger.WriteLine(_heating.ToString()); // first the temperature data XS1_DataObject maxdataobject = new XS1_DataObject(Properties.Settings.Default.ELVMAXIP, _heating.RoomName + "-" + _heating.DeviceName, ObjectTypes.Sensor, "heating_thermostat", DateTime.Now, _heating.RoomID, _heating.Temperature, _heating.ToString(), true); SensorCheckIgnoreConfiguration.AddToIgnoreList(maxdataobject.Name); XS1_DataQueue.Enqueue(maxdataobject); // then the low battery if exists if (_heating.LowBattery == BatteryStatus.lowbattery) { XS1_DataObject lowbatteryobject = new XS1_DataObject(Properties.Settings.Default.ELVMAXIP, _heating.RoomName + "-" + _heating.DeviceName, ObjectTypes.Sensor, "low_battery", DateTime.Now, _heating.RoomID, _heating.Temperature, _heating.ToString() + ", LowBattery", true); SensorCheckIgnoreConfiguration.AddToIgnoreList(lowbatteryobject.Name); XS1_DataQueue.Enqueue(lowbatteryobject); } if (_heating.Mode == ThermostatModes.boost) { XS1_DataObject boostmodeobject = new XS1_DataObject(Properties.Settings.Default.ELVMAXIP, _heating.RoomName + "-" + _heating.DeviceName, ObjectTypes.Sensor, "boost", DateTime.Now, _heating.RoomID, _heating.Temperature, _heating.ToString() + ", Boost", true); SensorCheckIgnoreConfiguration.AddToIgnoreList(boostmodeobject.Name); XS1_DataQueue.Enqueue(boostmodeobject); } } if (max_dataobject.DeviceType == DeviceTypes.ShutterContact) { ShutterContactDiff _shutter = (ShutterContactDiff)max_dataobject; // this is what is different on the ShutterContacts //ConsoleOutputLogger.WriteLine(_shutter.ToString()); // first the open/close status if (_shutter.ShutterState == ShutterContactModes.open) { XS1_DataObject maxdataobject = new XS1_DataObject(Properties.Settings.Default.ELVMAXIP, _shutter.RoomName + "-" + _shutter.DeviceName, ObjectTypes.Sensor, "shutter_contact", DateTime.Now, _shutter.RoomID, 1.0, _shutter.ToString(), true); SensorCheckIgnoreConfiguration.AddToIgnoreList(maxdataobject.Name); XS1_DataQueue.Enqueue(maxdataobject); } else { XS1_DataObject maxdataobject = new XS1_DataObject(Properties.Settings.Default.ELVMAXIP, _shutter.RoomName + "-" + _shutter.DeviceName, ObjectTypes.Sensor, "shutter_contact", DateTime.Now, _shutter.RoomID, 0.0, _shutter.ToString(), true); SensorCheckIgnoreConfiguration.AddToIgnoreList(maxdataobject.Name); XS1_DataQueue.Enqueue(maxdataobject); } // then the low battery if exists if (_shutter.LowBattery == BatteryStatus.lowbattery) { if (_shutter.ShutterState == ShutterContactModes.open) { XS1_DataObject lowbatteryobject = new XS1_DataObject(Properties.Settings.Default.ELVMAXIP, _shutter.RoomName + "-" + _shutter.DeviceName, ObjectTypes.Sensor, "low_battery", DateTime.Now, _shutter.RoomID, 1.0, _shutter.ToString() + ",LowBattery", true); SensorCheckIgnoreConfiguration.AddToIgnoreList(lowbatteryobject.Name); XS1_DataQueue.Enqueue(lowbatteryobject); } else { XS1_DataObject lowbatteryobject = new XS1_DataObject(Properties.Settings.Default.ELVMAXIP, _shutter.RoomName + "-" + _shutter.DeviceName, ObjectTypes.Sensor, "low_battery", DateTime.Now, _shutter.RoomID, 0.0, _shutter.ToString() + ",LowBattery", true); SensorCheckIgnoreConfiguration.AddToIgnoreList(lowbatteryobject.Name); XS1_DataQueue.Enqueue(lowbatteryobject); } } } } } #endregion #region Handle SolarLog events if (Properties.Settings.Default.SolarLogEnabled) { SolarLogDataSet solarlog_dataobject = null; if (SolarLog_DataQueue.TryDequeue(out solarlog_dataobject)) { // Pac XS1_DataQueue.Enqueue(new XS1_DataObject(Properties.Settings.Default.SolarLogURLDomain, "Pac", ObjectTypes.Sensor, "Pac", solarlog_dataobject.DateAndTime, 1, solarlog_dataobject.Pac, "solarlog," + Properties.Settings.Default.SolarLogURLDomain + ",Pac," + solarlog_dataobject.Pac + "," + solarlog_dataobject.DateAndTime.Ticks, true)); // aPdc XS1_DataQueue.Enqueue(new XS1_DataObject(Properties.Settings.Default.SolarLogURLDomain, "aPdc", ObjectTypes.Sensor, "aPdc", solarlog_dataobject.DateAndTime, 1, solarlog_dataobject.aPdc, "solarlog," + Properties.Settings.Default.SolarLogURLDomain + ",aPdc," + solarlog_dataobject.aPdc + "," + solarlog_dataobject.DateAndTime.Ticks, true)); // if Alarming is enabled, queue this SolarLog Event up for alarming... if (Properties.Settings.Default.AlarmingEnabled) { Alarming_Queue.Enqueue(solarlog_dataobject); } } } #endregion #region Handle Network Monitor events if (Properties.Settings.Default.NetworkMonitorEnabled) { NetworkMonitoringDataSet networkmonitor_dataobject = null; if (NetworkMonitor_Queue.TryDequeue(out networkmonitor_dataobject)) { if (networkmonitor_dataobject.Status == Org.Mentalis.Network.ICMP_Status.Success) { XS1_DataQueue.Enqueue(new XS1_DataObject(networkmonitor_dataobject.Descriptor, networkmonitor_dataobject.HostnameIP, ObjectTypes.Sensor, "Ping", networkmonitor_dataobject.TimeOfMeasurement, 2, 1, "OnlineCheck," + networkmonitor_dataobject.HostnameIP + "," + networkmonitor_dataobject.Descriptor + ",Online", true)); } else { XS1_DataQueue.Enqueue(new XS1_DataObject(networkmonitor_dataobject.Descriptor, networkmonitor_dataobject.HostnameIP, ObjectTypes.Sensor, "Ping", networkmonitor_dataobject.TimeOfMeasurement, 2, 0, "OnlineCheck," + networkmonitor_dataobject.HostnameIP + "," + networkmonitor_dataobject.Descriptor + ",Offline", true)); } // if Alarming is enabled, queue this Network Monitor Event up for alarming... if (Properties.Settings.Default.AlarmingEnabled) { Alarming_Queue.Enqueue(networkmonitor_dataobject); } } } #endregion } catch (Exception) { AcceptingCommands = false; //Thread.Sleep(1); } Thread.Sleep(1); } if (ELVMax != null) { ELVMax.running = false; } XS1.running = false; Thread.Sleep(200); // ... msecs period to wait for new input... }
public void Run() { ConsoleOutputLogger.WriteLine("Miataru Thread started"); miataruclient client = new miataruclient(); while (!Shutdown) { try { foreach (MiataruAccount Account in MiataruConfiguration.MiataruAccountConfigFile.MiataruAccounts) { // retrieve new data for this account... #region Retrieve Data List <MiataruLocation> Locations = client.GetLastLocationForDevice(Account.MiataruDeviceID, Account.MiataruServerURL); #endregion #region handle retrieved location data if (Locations != null) { // create a MiataruDataObject out of the last known location MiataruDataObject retrievedData = new MiataruDataObject(Account.Name, Locations[0].Device, Locations[0].Timestamp, Locations[0].Latitude, Locations[0].Longitude, Locations[0].HorizontalAccuracy); if (CurrentLocations.ContainsKey(retrievedData.DeviceID)) { // check if the coordinates have been updated... MiataruDataObject alreadyStored = CurrentLocations[Account.MiataruDeviceID]; if ((alreadyStored.Latitude != retrievedData.Latitude) || (alreadyStored.Longitude != retrievedData.Longitude)) { CurrentLocations[Account.MiataruDeviceID] = retrievedData; // store to disk miatarustore.Write(retrievedData.Serialize()); ConsoleOutputLogger.WriteLine("Miataru: " + retrievedData.AccountName + " - " + retrievedData.Latitude + "," + retrievedData.Longitude + "," + retrievedData.AccuracyInMeters); } } else { // it's new! add it! CurrentLocations.Add(retrievedData.DeviceID, retrievedData); miatarustore.Write(retrievedData.Serialize()); ConsoleOutputLogger.WriteLine("Miataru: " + retrievedData.AccountName + " - " + retrievedData.Latitude + "," + retrievedData.Longitude + "," + retrievedData.AccuracyInMeters); } } else { ConsoleOutputLogger.WriteLine("Miataru returned NULL for " + Account.MiataruDeviceID + " on " + Account.MiataruServerURL); } #endregion } } catch (Exception e) { ConsoleOutputLogger.WriteLine(e.Message + " - " + e.StackTrace); Thread.Sleep(100); } Thread.Sleep(MiataruUpdateTime); } }
public ProxyResponse Proxy(String URL) { ProxyResponse proxy_Response = new ProxyResponse(); ProxyElement p_element = null; // we need to find out what we need to replace foreach (ProxyElement element in HTTPProxyConfiguration.ProxyElements) { if (URL.StartsWith(element.ActivationURL)) { p_element = element; // obviously we found a hit break; } } // /control?user=admin&pwd=xxx&callback=actuators&cmd=get_list_actuators ConsoleOutputLogger.WriteLine("Proxy: " + URL + " - " + URL.Replace(p_element.ActivationURL, p_element.OutgoingMappingURL)); if (p_element != null) { WebRequest wrGetURL = WebRequest.Create(URL.Replace(p_element.ActivationURL, p_element.OutgoingMappingURL)); HttpWebResponse response = (HttpWebResponse)wrGetURL.GetResponse(); if (response.StatusCode != HttpStatusCode.OK) { proxy_Response.response = response; proxy_Response.Content = "Something wicked happened."; return(proxy_Response); } proxy_Response.response = response; // we will read data via the response stream proxy_Response.Content = new StreamReader(response.GetResponseStream()).ReadToEnd(); #region Check for XS1 trigger URLs and if found and ELV MAX is active inject actors and sensors if (ELVMAX != null) { if (ELVMAX.theHouse != null) { // we've found a House, did we find a trigger here? #region get_list_actuators if (URL.Contains("cmd=get_list_actuators")) { proxy_Response.Content = VirtualXS1.Inject_get_list_actuators(proxy_Response.Content, ELVMAX.theHouse); } #endregion #region get_list_sensors if (URL.Contains("cmd=get_list_sensors")) { proxy_Response.Content = VirtualXS1.Inject_get_list_sensors(proxy_Response.Content, ELVMAX.theHouse); } #endregion } } #endregion return(proxy_Response); } return(null); }
public void Run() { ConsoleOutputLogger.WriteLine("Alarming Thread started"); while (!Shutdown) { try { IAlarmingEvent dataobject = null; if (Alarming_Queue.TryDequeue(out dataobject)) { // we should get events from all sorts of devices here - let's take them and check if they // are eventually matching the activators - if they do we check against the other // data storages to follow up with the alarms... // check if we find this in the alarms... foreach (Alarm _alarm in AlarmingConfiguration.Alarms.Alarms) { foreach (Activator _activator in _alarm.activators) { // activator names are case sensitive!!! if (dataobject.AlarmingName() == _activator.name) { // we got a positive activator match here! // now check further circumstances... #region XS1 Events if ((_activator.device.ToUpper() == "XS1") && (dataobject.AlarmingType() == AlarmingEventType.XS1Event)) { // now we got an alarm triggering this activator and device... // check if the type matches... XS1_DataObject xs1_data = (XS1_DataObject)dataobject; if (_activator.type.ToUpper() == xs1_data.TypeName.ToUpper()) { // for the value comparison convert the given value to a double... double comp_value = Convert.ToDouble(_activator.value); // it's the right typename... // now we gotta check for the right value there... Boolean alarm_activated = false; #region Activator Value Comparison switch (_activator.comparison) { case "==": if (comp_value == xs1_data.Value) { // hurray, everything matches! Activate this event!!! alarm_activated = true; } break; case "<=": if (comp_value <= xs1_data.Value) { // hurray, everything matches! Activate this event!!! alarm_activated = true; } break; case ">=": if (comp_value >= xs1_data.Value) { // hurray, everything matches! Activate this event!!! alarm_activated = true; } break; } #endregion #region do the sensor and actor checks... // TODO: this is very rough - needs to be worked out more later on... // for the moment it is just a actor check - MORE HERE !!!!!!!! if (alarm_activated) { foreach (Actorcheck _actor in _alarm.actorchecks) { #region XS1 actors... if (_actor.device.ToUpper() == "XS1") { if (KnownActorStates.KnownActorStatuses.ContainsKey(_actor.name)) { // there's an actor... current_actor_status status = (current_actor_status)KnownActorStates.KnownActorStatuses[_actor.name]; // TODO: what about actor types!? if (_actor.value.ToUpper() == "ON") { // so it should be on... if (status.Status != actor_status.On) { alarm_activated = false; } } if (_actor.value.ToUpper() == "OFF") { // so it should be off... if (status.Status != actor_status.Off) { alarm_activated = false; } } } } #endregion } } #endregion if (alarm_activated) { ConsoleOutputLogger.WriteLine("!!!! ALARM - " + _alarm.name + " - ALARM !!!!"); // authenticate Telekom if (Properties.Settings.Default.UseTelekomSMSInsteadofSMS77) { TelekomSMSGateway = new TelekomSendSMSGateway(Properties.Settings.Default.TelekomSMSClientID, Properties.Settings.Default.TelekomSMSClientSecret); } // send out the SMS... foreach (Smsrecipient recipient in _alarm.smsrecipients) { ConsoleOutputLogger.WriteLine("Sending Alarm SMS to " + recipient.number + " for alarm " + _alarm.name); try { if (!Properties.Settings.Default.UseTelekomSMSInsteadofSMS77) { SMSGateway.SendSMS(recipient.number, _alarm.message, Properties.Settings.Default.AlarmingSMS77SenderNumber, false, false, SMSType.quality); } else { TelekomSMSGateway.Send(recipient.number, _alarm.message, Properties.Settings.Default.AlarmingSMS77SenderNumber); } } catch (Exception e) { ConsoleOutputLogger.WriteLine("SMS Sending Exception: " + e.Message); } } } } } #endregion #region ELVMAX Events if ((_activator.device.ToUpper() == "ELVMAX") && (dataobject.AlarmingType() == AlarmingEventType.ELVMAXEvent)) { //ConsoleOutputLogger.WriteLine("ELVMAX: " + _activator.device); // now we got an alarm triggering this activator and device... // check if the type matches... IDeviceDiffSet diffset = (IDeviceDiffSet)dataobject; //ConsoleOutputLogger.WriteLine("ELVMAX: " + diffset.DeviceName); //ConsoleOutputLogger.WriteLine("ELVMAX: " + diffset.RoomName); //ConsoleOutputLogger.WriteLine("ELVMAX: " + _activator.type); //ConsoleOutputLogger.WriteLine("ELVMAX: " + _activator.name); // for now only shuttercontacts are interesting if ((_activator.type.ToUpper() == "SHUTTERCONTACT") && (diffset.DeviceType == DeviceTypes.ShutterContact) && (_activator.name == diffset.DeviceName)) { //ConsoleOutputLogger.WriteLine("ELVMAX Shuttercontact"); ShutterContactDiff shutterdiff = (ShutterContactDiff)diffset; //ConsoleOutputLogger.WriteLine("ELVMAX: "+shutterdiff.ToString()); ShutterContactModes activatorstate = ShutterContactModes.unchanged; Boolean alarm_activated = false; if (_activator.value.ToUpper() == "OPEN") { activatorstate = ShutterContactModes.open; } if (_activator.value.ToUpper() == "CLOSED") { activatorstate = ShutterContactModes.closed; } if (activatorstate == shutterdiff.ShutterState) { alarm_activated = true; } #region do the sensor and actor checks... // TODO: this is very rough - needs to be worked out more later on... // for the moment it is just a actor check - MORE HERE !!!!!!!! if (alarm_activated) { foreach (Actorcheck _actor in _alarm.actorchecks) { #region XS1 actors... if (_actor.device.ToUpper() == "XS1") { if (KnownActorStates.KnownActorStatuses.ContainsKey(_actor.name)) { // there's an actor... current_actor_status status = (current_actor_status)KnownActorStates.KnownActorStatuses[_actor.name]; // TODO: what about actor types!? if (_actor.value.ToUpper() == "ON") { // so it should be on... if (status.Status != actor_status.On) { alarm_activated = false; } } if (_actor.value.ToUpper() == "OFF") { // so it should be off... if (status.Status != actor_status.Off) { alarm_activated = false; } } } } #endregion } } #endregion if (alarm_activated) { ConsoleOutputLogger.WriteLine("!!!! ALARM - " + _alarm.name + " - ALARM !!!!"); // authenticate Telekom if (Properties.Settings.Default.UseTelekomSMSInsteadofSMS77) { TelekomSMSGateway = new TelekomSendSMSGateway(Properties.Settings.Default.TelekomSMSClientID, Properties.Settings.Default.TelekomSMSClientSecret); } // send out the SMS... foreach (Smsrecipient recipient in _alarm.smsrecipients) { ConsoleOutputLogger.WriteLine("Sending Alarm SMS to " + recipient.number + " for alarm " + _alarm.name); try { if (!Properties.Settings.Default.UseTelekomSMSInsteadofSMS77) { SMSGateway.SendSMS(recipient.number, _alarm.message, Properties.Settings.Default.AlarmingSMS77SenderNumber, false, false, SMSType.quality); } else { TelekomSMSGateway.Send(recipient.number, _alarm.message, Properties.Settings.Default.AlarmingSMS77SenderNumber); } } catch (Exception e) { ConsoleOutputLogger.WriteLine("SMS Sending Exception: " + e.Message); } } } } } #endregion // TODO: ------------------------------ #region SolarLog Events if ((_activator.device.ToUpper() == "SOLARLOG") && (dataobject.AlarmingType() == AlarmingEventType.SolarLogEvent)) { // now we got an alarm triggering this activator and device... } #endregion #region Network Monitor Events if ((_activator.device.ToUpper() == "NETWORKMONITOR") && (dataobject.AlarmingType() == AlarmingEventType.NetworkingEvent)) { // now we got an alarm triggering this activator and device... } #endregion #region Google Latitude Events if ((_activator.device.ToUpper() == "GOOGLELATITUDE") && (dataobject.AlarmingType() == AlarmingEventType.GoogleLatitudeEvent)) { // now we got an alarm triggering this activator and device... } #endregion } } } } } catch (Exception e) { //Shutdown = true; ConsoleOutputLogger.WriteLine("Alarming Exception: " + e.Message); ConsoleOutputLogger.WriteLine("Stopping Alarming Execution!"); Thread.Sleep(100); } Thread.Sleep(10); } }
// this is the network monitoring script public void Run() { ConsoleOutputLogger.WriteLine("Starting up the Network Monitoring..."); ICMP pinger = new ICMP(); while (running) { foreach (NetworkMonitoringHost Host in NetworkMonitorConfiguration.NetworkHosts) { // start pinging around ICMP_PingResult result = null; try { result = pinger.Ping(Host.IPAdressOrHostname, 1, 500); } catch (Exception) { //ConsoleOutputLogger.WriteLine("NetworkMonitor Exception: "+e.Message); result = new ICMP_PingResult(); result.Status = ICMP_Status.TimeOut; result.hostIP = null; } // we got a result... if (result != null) { // it's already in the list if (OnOfflineList.ContainsKey(Host.IPAdressOrHostname)) { if (OnOfflineList[Host.IPAdressOrHostname] == true) // this one was online before... { if (result.Status == ICMP_Status.TimeOut) { // it's now offline... OnOfflineList[Host.IPAdressOrHostname] = false; NetworkMonitoringDataSet ds_result = new NetworkMonitoringDataSet(); ds_result.AverageRoundtripMS = result.AverageRoundtripMS; ds_result.Descriptor = Host.Descriptor; ds_result.HostnameIP = Host.IPAdressOrHostname; ds_result.Status = result.Status; ds_result.TimeOfMeasurement = result.TimeOfMeasurement; iQueue.Enqueue(ds_result); } } else { if (result.Status == ICMP_Status.Success) { // it's now online... OnOfflineList[Host.IPAdressOrHostname] = true; NetworkMonitoringDataSet ds_result = new NetworkMonitoringDataSet(); ds_result.AverageRoundtripMS = result.AverageRoundtripMS; ds_result.Descriptor = Host.Descriptor; ds_result.HostnameIP = Host.IPAdressOrHostname; ds_result.Status = result.Status; ds_result.TimeOfMeasurement = result.TimeOfMeasurement; iQueue.Enqueue(ds_result); } } } else { if (result.Status == ICMP_Status.Success) { OnOfflineList.Add(Host.IPAdressOrHostname, true); } else { OnOfflineList.Add(Host.IPAdressOrHostname, false); } // enqueue NetworkMonitoringDataSet ds_result = new NetworkMonitoringDataSet(); ds_result.AverageRoundtripMS = result.AverageRoundtripMS; ds_result.Descriptor = Host.Descriptor; ds_result.HostnameIP = Host.IPAdressOrHostname; ds_result.Status = result.Status; ds_result.TimeOfMeasurement = result.TimeOfMeasurement; iQueue.Enqueue(ds_result); } } } Thread.Sleep(NetworkMonitorUpdateTime); } }
// this is the ELV MAX! Cube monitoring script public void Run() { while (running) { TcpClient client; NetworkStream stream; Dictionary <String, IMAXDevice> currentHouse = new Dictionary <string, IMAXDevice>(); #region Update House try { // now fill that with the initial handshake data... #region Initial connect and retrieving everything we get from the cube // network connect and first initialization client = new TcpClient(); client.Connect(Hostname, Port); stream = client.GetStream(); // the read buffer (chosen quite big) byte[] myReadBuffer = new byte[4096 * 8]; List <String> Messages = new List <string>(); // to build the complete message StringBuilder myCompleteMessage = new StringBuilder(); int numberOfBytesRead = 0; MAXEncodeDecode DecoderEncoder = new MAXEncodeDecode(); keepRunning = true; // Incoming message may be larger than the buffer size. do { myCompleteMessage = new StringBuilder(); stream.ReadTimeout = 1000; try { numberOfBytesRead = stream.Read(myReadBuffer, 0, myReadBuffer.Length); myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead)); Messages.Add(myCompleteMessage.ToString()); } catch (Exception) { previousHouse = null; // everything to start theHouse = new House(); keepRunning = false; } }while(keepRunning); #endregion ConsoleOutputLogger.WriteLine("ELV MAX Cube connected..."); #region preprocess List <String> PreProcessedMessages = new List <string>(); foreach (String _Message in Messages) { if (_Message.Remove(_Message.Length - 2).Contains("\r\n")) { String[] PMessages = _Message.Remove(_Message.Length - 2).Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (String pmessage in PMessages) { PreProcessedMessages.Add(pmessage.Replace("\r", "") + "\r\n"); } } else { PreProcessedMessages.Add(_Message); } } #endregion #region process // Analyze and Output Messages, feed them to the decoder foreach (String _Message in PreProcessedMessages) { //IMAXMessage Message = DecoderEncoder.ProcessMessage(_Message.ToString(), theHouse); // if (Message != null) // { // ConsoleOutputLogger.WriteLine(_Message.ToString()); // ConsoleOutputLogger.WriteLine(Message.ToString()); // ConsoleOutputLogger.WriteLine(""); // } DecoderEncoder.ProcessMessage(_Message.ToString(), theHouse); } #endregion while (running) { // when we are here, we got a filled "theHouse" which does contain first hand L message information previousHouse = theHouse.GetAllDevicesInADictionary(); #region send L: request and get all the feedback System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); byte[] args_data_buffer = enc.GetBytes("l:\r\n"); Messages = new List <string>(); keepRunning = true; // Incoming message may be larger than the buffer size. stream.Write(args_data_buffer, 0, args_data_buffer.Length); do { myCompleteMessage = new StringBuilder(); stream.ReadTimeout = 1000; try { numberOfBytesRead = stream.Read(myReadBuffer, 0, myReadBuffer.Length); myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead)); Messages.Add(myCompleteMessage.ToString()); } catch (Exception) { keepRunning = false; } }while(keepRunning); #endregion #region preprocess PreProcessedMessages = new List <string>(); foreach (String _Message in Messages) { if (_Message.Remove(_Message.Length - 2).Contains("\r\n")) { String[] PMessages = _Message.Remove(_Message.Length - 2).Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (String pmessage in PMessages) { PreProcessedMessages.Add(pmessage.Replace("\r", "") + "\r\n"); } } else { PreProcessedMessages.Add(_Message); } } #endregion #region process // Analyze and Output Messages, feed them to the decoder foreach (String _Message in PreProcessedMessages) { //IMAXMessage Message = DecoderEncoder.ProcessMessage(_Message.ToString(), theHouse); // if (Message != null) // { // ConsoleOutputLogger.WriteLine(_Message.ToString()); // ConsoleOutputLogger.WriteLine(Message.ToString()); // ConsoleOutputLogger.WriteLine(""); // } currentHouse = new Dictionary <string, IMAXDevice>(); DecoderEncoder.ProcessLMessage(_Message.ToString(), theHouse, currentHouse); } #endregion #region Diff the house if (previousHouse != null) { // only if we already got two houses in here... List <IDeviceDiffSet> differences = DiffHouse.CalculateDifferences(previousHouse, currentHouse); if (differences.Count != 0) { #region enqueue the difference-sets into the data queue foreach (IDeviceDiffSet _difference in differences) { iQueue.Enqueue(_difference); } #endregion } } #endregion theHouse.UpdateDevices(currentHouse); // update appropriate devices and in given intervals output non updated TimeSpan _lastUpdate = DateTime.Now - LastReStoring; // auto-update every n ... minutes if (_lastUpdate.TotalSeconds > Properties.Settings.Default.ELVMAXSensorReStoringSec) { LastReStoring = DateTime.Now; foreach (IMAXDevice _device in currentHouse.Values) { #region Heating Thermostat if (_device.Type == DeviceTypes.HeatingThermostat) { HeatingThermostat _heating = (HeatingThermostat)_device; HeatingThermostatDiff _queueable = new HeatingThermostatDiff(_device.Name, _device.AssociatedRoom.RoomID, _device.AssociatedRoom.RoomName); if (_heating.LowBattery) { _queueable.LowBattery = BatteryStatus.lowbattery; } else { _queueable.LowBattery = BatteryStatus.ok; } _queueable.Mode = _heating.Mode; _queueable.Temperature = _heating.Temperature; if (_queueable.Temperature != 0) { iQueue.Enqueue(_queueable); } } #endregion #region ShutterContact if (_device.Type == DeviceTypes.ShutterContact) { ShutterContact _shutter = (ShutterContact)_device; ShutterContactDiff _queueable = new ShutterContactDiff(_device.Name, _device.AssociatedRoom.RoomID, _device.AssociatedRoom.RoomName); if (_shutter.LowBattery) { _queueable.LowBattery = BatteryStatus.lowbattery; } else { _queueable.LowBattery = BatteryStatus.ok; } _queueable.ShutterState = _shutter.ShutterState; iQueue.Enqueue(_queueable); } #endregion } } Thread.Sleep(MAXUpdateTime); } } catch (Exception e) { ConsoleOutputLogger.WriteLine(e.Message); Thread.Sleep(Properties.Settings.Default.ELVMAXReconnectTimeMsec); ConsoleOutputLogger.WriteLine("ELV MAX Cube reconnect..."); //stream.Close(); //client.Close(); } #endregion } }
/// <summary> /// Run this instance. /// </summary> public void Run() { ConsoleOutputLogger.WriteLine("Starting Actor Re-Switching."); DateTime LastCheckpoint = DateTime.Now; TimeSpan SinceLastCheckpoint = new TimeSpan(); while (!_Shutdown) { // we start by // checking how much time passed since we were here the last time SinceLastCheckpoint = DateTime.Now - LastCheckpoint; //Console.WriteLine(SinceLastCheckpoint.TotalMinutes); // now we can do something every minute or so if (SinceLastCheckpoint.TotalMinutes >= hacs.Properties.Settings.Default.SwitchAgainCheckpointMinutes) { //ConsoleOutputLogger.WriteLine("Sensor Checkpoint"); LastCheckpoint = DateTime.Now; #region Switch Actors again with same state // go through all the known actor status codes and try to send // them again to the actor one after another // TODO: this try is just here to handle enum exceptions just in case, introduce locking! try { foreach (current_actor_status status in KnownActorStates.KnownActorStatuses.Values) { // if this actor was switched within the last configured minutes we switch it again to the exact same // state, just to make sure that they were successfully switched (just ON/OFF states) if ((DateTime.Now - status.LastUpdate).TotalMinutes <= hacs.Properties.Settings.Default.SwitchAgainTimeWindowMinutes) { bool ignorethisone = false; lock (OnWaitOffList) { if (OnWaitOffList.Contains(status.ActorName)) { //Console.WriteLine(status.ActorName+" is on the ignorelist"); ignorethisone = true; } } if (!ignorethisone) { ConsoleOutputLogger.WriteLine("Switching again actor " + status.ActorName + "(" + (DateTime.Now - status.LastUpdate).TotalMinutes + ")"); // yes, within the last given number of minutes set_state_actuator.set_state_actuator ssa = new set_state_actuator.set_state_actuator(); #region ON state if (status.Status == actor_status.On) { // set on temporary blacklist lock (TemporaryBlacklist) { TemporaryBlacklist.Add(status.ActorName); } ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, status.ActorName, "ON", XS1_Configuration); } #endregion #region OFF state if (status.Status == actor_status.Off) { // set on temporary blacklist lock (TemporaryBlacklist) { TemporaryBlacklist.Add(status.ActorName); } ssa.SetStateActuatorPreset(hacs.Properties.Settings.Default.XS1, hacs.Properties.Settings.Default.Username, hacs.Properties.Settings.Default.Password, status.ActorName, "OFF", XS1_Configuration); } #endregion } } Thread.Sleep(2000); } } catch (Exception) { } #endregion } Thread.Sleep(10000); // just check every 10 seconds... } }