public HttpServer(Int32 HTTP_Port, String HTTP_ListeningIP, String HTTP_DocumentRoot, TinyOnDiskStorage _Storage, XS1Configuration _XS1_Configuration, ConsoleOutputLogger Logger, MAXMonitoringThread _ELVMAXMonitoringThread) { HTTPServer_Port = HTTP_Port; HTTPServer_ListeningIP = HTTP_ListeningIP; HTTPServer_DocumentRoot = HTTP_DocumentRoot; Storage = _Storage; XS1_Configuration = _XS1_Configuration; ConsoleOutputLogger = Logger; ELVMAXMonitoringThread = _ELVMAXMonitoringThread; }
/// <summary> /// Each HTTP processor object handles one client. If Keep-Alive is enabled then this /// object will be reused for subsequent requests until the client breaks keep-alive. /// This usually happens when it times out. Because this could easily lead to a DoS /// attack, we keep track of the number of open processors and only allow 100 to be /// persistent active at any one time. Additionally, we do not allow more than 500 /// outstanding requests. /// </summary> /// <param name="docRoot">Root-Directory of the HTTP Server</param> /// <param name="s">the Socket to work with</param> /// <param name="webserver">the "master" HttpServer Object of this Client</param> public HttpProcessor(Socket s, String HTTP_DocumentRoot, TinyOnDiskStorage Storage, XS1Configuration _XS1_Configuration, ConsoleOutputLogger Logger, MAXMonitoringThread ELVMAXMonitoring) { this.s = s; HTTPServer_DocumentRoot = HTTP_DocumentRoot; JSON_Data = new JSONData(Storage,Logger); docRootFile = new FileInfo(HTTPServer_DocumentRoot); headers = new Hashtable(); XS1_Configuration = _XS1_Configuration; ConsoleOutputLogger = Logger; internal_proxy = new HTTPProxy(ConsoleOutputLogger,ELVMAXMonitoring); ELVMAX = ELVMAXMonitoring; SensorDataStore = Storage; }
public static string Generate(MAXMonitoringThread ELVMAX,TinyOnDiskStorage SensorDataStore, String ObjectName, String ObjectTypeName, DateTime StartDateTime, DateTime EndDateTime) { SwimLaneRootObject _root = new SwimLaneRootObject(); _root.items = new System.Collections.Generic.List<ItemJSON>(); _root.lanes = new System.Collections.Generic.List<LaneJSON>(); #region fill the lanes // we need to have the data here // we shall have a cache (it's private for the other json methods... what about it?) // we need to have a selector which sensors need to be outputted... lock (SensorDataStore.InMemoryIndex) { foreach (OnDiscAdress ondisc in SensorDataStore.InMemoryIndex) { if (ondisc.CreationTime >= StartDateTime.Ticks) { if (ondisc.CreationTime <= EndDateTime.Ticks) { // we are in the right timespan // is this the right sensor? XS1_DataObject dataobject = ReadFromCache(SensorDataStore,ondisc); if (dataobject.TypeName == ObjectTypeName) { if (dataobject.Name == ObjectName) { // okay we got what we want... } } } } } } #endregion return ""; }
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, XS1_Configuration, ConsoleOutputLogger, ELVMax); Thread http_server_thread = new Thread(new ThreadStart(httpServer.listen)); http_server_thread.Start(); // Start Service Monitorng thread ServiceMonitor monitor = new ServiceMonitor(ConsoleOutputLogger); Thread serviceMonitorThread = new Thread(new ThreadStart(monitor.Run)); serviceMonitorThread.Start(); while (!Shutdown) { try { #region Handle XS1 events XS1_DataObject dataobject = null; if (XS1_DataQueue.TryDequeue(out dataobject)) { if (dataobject.Type == ObjectTypes.Actor) { 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 (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); // 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); // check what action is going to happen now... if (Element.ActionToRunName == actor_status.On) { ssa.SetStateActuatorPreset(xs1_data_logging.Properties.Settings.Default.XS1, xs1_data_logging.Properties.Settings.Default.Username, xs1_data_logging.Properties.Settings.Default.Password, Element.ActorToSwitchName, "ON", XS1_Configuration); } if (Element.ActionToRunName == actor_status.Off) { ssa.SetStateActuatorPreset(xs1_data_logging.Properties.Settings.Default.XS1, xs1_data_logging.Properties.Settings.Default.Username, xs1_data_logging.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(xs1_data_logging.Properties.Settings.Default.XS1, xs1_data_logging.Properties.Settings.Default.Username, xs1_data_logging.Properties.Settings.Default.Password, Element.ActorToSwitchName, "OFF", XS1_Configuration); else if (Status.Status == actor_status.Off) ssa.SetStateActuatorPreset(xs1_data_logging.Properties.Settings.Default.XS1, xs1_data_logging.Properties.Settings.Default.Username, xs1_data_logging.Properties.Settings.Default.Password, Element.ActorToSwitchName, "ON", XS1_Configuration); } else ssa.SetStateActuatorPreset(xs1_data_logging.Properties.Settings.Default.XS1, xs1_data_logging.Properties.Settings.Default.Username, xs1_data_logging.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(xs1_data_logging.Properties.Settings.Default.XS1, xs1_data_logging.Properties.Settings.Default.Username, xs1_data_logging.Properties.Settings.Default.Password, Element.ActorToSwitchName, "ON_WAIT_OFF", XS1_Configuration); } } } } } 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)) { 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()); 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"); 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"); 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()); 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()); 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"); 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"); 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)); // 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)); } } #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 HTTPProxy(ConsoleOutputLogger Logger, MAXMonitoringThread ELVMAXMonitoringThread) { ConsoleOutputLogger = Logger; ELVMAX = ELVMAXMonitoringThread; }