/// <summary> /// This method calculates the difference between house1 and house2 - whereas house1 is the old house2 the new one /// </summary> public static List<IDeviceDiffSet> CalculateDifferences(Dictionary<String,IMAXDevice> DevicesHouse1, Dictionary<String,IMAXDevice> DevicesHouse2) { List<IDeviceDiffSet> Differences = new List<IDeviceDiffSet>(); foreach(KeyValuePair<String,IMAXDevice> House1KVPair in DevicesHouse1) { // now we have a device from house 1 - we need to get that same device in house 2 if (DevicesHouse2.ContainsKey(House1KVPair.Key)) { // we got it IMAXDevice House2Device = DevicesHouse2[House1KVPair.Key]; if (House1KVPair.Value.Type == DeviceTypes.HeatingThermostat) { // HeatingThermostat HeatingThermostatDiff Diff = null; HeatingThermostat Device1 = (HeatingThermostat)House1KVPair.Value; HeatingThermostat Device2 = (HeatingThermostat)House2Device; if (Device1.LowBattery != Device2.LowBattery) { if (Diff == null) Diff = new HeatingThermostatDiff(Device2.Name,Device2.AssociatedRoom.RoomID,Device2.AssociatedRoom.RoomName); if (Device2.LowBattery) Diff.LowBattery = BatteryStatus.lowbattery; else Diff.LowBattery = BatteryStatus.ok; } if (Device1.Mode != Device2.Mode) { if (Diff == null) Diff = new HeatingThermostatDiff(Device2.Name,Device2.AssociatedRoom.RoomID,Device2.AssociatedRoom.RoomName); Diff.Mode = Device2.Mode; } if (Device1.Temperature != Device2.Temperature) { if (Diff == null) Diff = new HeatingThermostatDiff(Device2.Name,Device2.AssociatedRoom.RoomID,Device2.AssociatedRoom.RoomName); Diff.Temperature = Device2.Temperature; } if (Diff != null) { if (Diff.Temperature != 0) Differences.Add(Diff); } } else if (House1KVPair.Value.Type == DeviceTypes.ShutterContact) { // ShutterContact ShutterContactDiff Diff = null; ShutterContact Device1 = (ShutterContact)House1KVPair.Value; ShutterContact Device2 = (ShutterContact)House2Device; if (Device1.LowBattery != Device2.LowBattery) { if (Diff == null) Diff = new ShutterContactDiff(Device2.Name,Device2.AssociatedRoom.RoomID,Device2.AssociatedRoom.RoomName); if (Device2.LowBattery) Diff.LowBattery = BatteryStatus.lowbattery; else Diff.LowBattery = BatteryStatus.ok; } if (Device1.ShutterState != Device2.ShutterState) { if (Diff == null) Diff = new ShutterContactDiff(Device2.Name,Device2.AssociatedRoom.RoomID,Device2.AssociatedRoom.RoomName); Diff.ShutterState = Device2.ShutterState; } if (Diff != null) { Differences.Add(Diff); } } } } return Differences; }
// 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 } }