public IMAXMessage ProcessLMessage(String Message, House _House, Dictionary<String, IMAXDevice> _currentHouseDevices) { if (Message.Length < 2) throw new MAXException("Unable to process message: "+Message); // check what type of message we got and return the processed values if (Message.StartsWith("L:")) return new L_Message(Message, _House, _currentHouseDevices); //throw new NotImplementedException(); return null; }
/// <summary> /// Inject into an existing get_list_actuator JSON output of an ezcontrol XS1 device /// </summary> public static String Inject_get_list_actuators(String XS1_get_list_actuators_response, House ELVMAXHouse) { Int32 id = 65; Int32 numberofCharactersToDelete = XS1_get_list_actuators_response.IndexOf('('); String Start = XS1_get_list_actuators_response.Remove(numberofCharactersToDelete + 1); String Prepared = XS1_get_list_actuators_response.Remove(0, numberofCharactersToDelete + 1); Prepared = Prepared.Remove(Prepared.Length - 4, 4); ActorJSON_Root deserializedActors = JsonConvert.DeserializeObject<ActorJSON_Root>(Prepared); String SensorJSON = JsonConvert.SerializeObject(deserializedActors); SensorJSON = Start + SensorJSON + ")"; return XS1_get_list_actuators_response; }
// initializes this class and processes the given Input Message and fills the Message Fields public C_Message(String RAW_Message, House _House) { if (RAW_Message.Length < 2) throw new MAXException("Unable to process the RAW Message."); if (!RAW_Message.StartsWith("C:")) throw new MAXException("Unable to process the RAW Message. Not a C Message."); String[] SplittedRAWMessage = RAW_Message.Remove(0,2).Split(new char[1] { ',' }); if (SplittedRAWMessage.Length >= 2) { RFAdress = SplittedRAWMessage[0];//Int32.Parse(SplittedRAWMessage[0],System.Globalization.NumberStyles.HexNumber); RawMessageDecoded = Base64.Decode(SplittedRAWMessage[1]); } else throw new MAXException("Unable to process C Message. Not enough content."); }
public IMAXMessage ProcessMessage(String Message, House _House) { if (Message.Length < 2) throw new MAXException("Unable to process message: "+Message); // check what type of message we got and return the processed values if (Message.StartsWith("M:")) return new M_Message(Message, _House); if (Message.StartsWith("H:")) return new H_Message(Message, _House); //if (Message.StartsWith("C:")) // return new C_Message(Message, _House); if (Message.StartsWith("L:")) return new L_Message(Message, _House); //throw new NotImplementedException(); return null; }
// initializes this class and processdes the given Input Message and fills the Message Fields public H_Message(String RAW_Message, House _House) { if (RAW_Message.Length < 2) throw new MAXException("Unable to process the RAW Message."); if (!RAW_Message.StartsWith("H:")) throw new MAXException("Unable to process the RAW Message. Not a H Message."); String[] SplittedRAWMessage = RAW_Message.Remove(0,2).Split(new char[1] { ',' }); if (SplittedRAWMessage.Length >= 3) { MAXserialNumber = SplittedRAWMessage[0]; RFAddress = SplittedRAWMessage[1];//Int32.Parse(SplittedRAWMessage[1],System.Globalization.NumberStyles.HexNumber); FirmwareVersion = Int32.Parse(SplittedRAWMessage[2],System.Globalization.NumberStyles.HexNumber); HTTPConnId = SplittedRAWMessage[4]; CubeDateTime = DecodeDateTime(SplittedRAWMessage[7],SplittedRAWMessage[8]); _House.CubeInformation = this; } else throw new MAXException("Unable to process H Message. Not enough content."); }
// initializes this class and processes the given Input Message and fills the Message Fields public M_Message(String RAW_Message, House _House) { thisHouse = _House; if (RAW_Message.Length < 2) throw new MAXException("Unable to process the RAW Message."); if (!RAW_Message.StartsWith("M:")) throw new MAXException("Unable to process the RAW Message. Not a M Message."); String[] SplittedRAWMessage = RAW_Message.Remove(0,2).Split(new char[1] { ',' }); if (SplittedRAWMessage.Length >= 3) { Index = Int32.Parse(SplittedRAWMessage[0],System.Globalization.NumberStyles.HexNumber); Count = Int32.Parse(SplittedRAWMessage[1],System.Globalization.NumberStyles.HexNumber); RawMessageDecoded = Base64.Decode(SplittedRAWMessage[2]); // System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); // Console.WriteLine(enc.GetString (RawMessageDecoded)); // StringBuilder hexlist = new StringBuilder(); // // foreach(Byte _byte in RawMessageDecoded) // { // hexlist.Append(_byte.ToString()+" "); // } Int32 Cursor = 2; // now go deeper Byte RoomCount = RawMessageDecoded[Cursor]; Cursor++; #region Rooms // go through every room for(byte roomnumber=1;roomnumber<=RoomCount;roomnumber++) { Room newRoom = new Room(thisHouse); newRoom.RoomID = RawMessageDecoded[Cursor]; Cursor++; Byte RoomNameLength = RawMessageDecoded[Cursor]; Cursor++; byte[] RoomName = new byte[RoomNameLength]; for(Byte j=0;j<=RoomNameLength-1;j++) { //RoomName.Append((char)RawMessageDecoded[Cursor]); RoomName[j] = RawMessageDecoded[Cursor]; Cursor++; } newRoom.RoomName = System.Text.Encoding.UTF8.GetString(RoomName); StringBuilder RFAddress_Buffer = new StringBuilder(); for(Byte j=0;j<=3-1;j++) { RFAddress_Buffer.Append(RawMessageDecoded[Cursor]); Cursor++; } newRoom.RFAddress = RFAddress_Buffer.ToString();//Int32.Parse(RFAddress_Buffer.ToString(),System.Globalization.NumberStyles.HexNumber); _House.Rooms.Add(newRoom); } #region Devices //newRoom.RFAddress = Int32.Parse(RFAddress.ToString(),System.Globalization.NumberStyles.HexNumber); Byte DeviceCount = RawMessageDecoded[Cursor]; Cursor++; // go through all the devices in here for(byte devicenumber=1;devicenumber<=DeviceCount;devicenumber++) { // read in the device IMAXDevice newDevice = new UnknownDevice(); #region Determine DeviceType Byte DevType = RawMessageDecoded[Cursor]; Cursor++; switch(DevType) { case 1: newDevice = new HeatingThermostat(); break; case 2: newDevice = new HeatingThermostatPlus(); break; case 3: newDevice = new WallMountedThermostat(); break; case 4: newDevice = new ShutterContact(); break; case 5: newDevice = new PushButton(); break; default: break; } #endregion StringBuilder DeviceRFAddress = new StringBuilder(); for(Byte j=0;j<=3-1;j++) { DeviceRFAddress.Append(RawMessageDecoded[Cursor]); Cursor++; } newDevice.RFAddress = DeviceRFAddress.ToString();//Int32.Parse(DeviceRFAddress.ToString(),System.Globalization.NumberStyles.HexNumber); StringBuilder DeviceSerialNumber = new StringBuilder(); for(Byte j=0;j<=10-1;j++) { DeviceSerialNumber.Append((char)RawMessageDecoded[Cursor]); Cursor++; } newDevice.SerialNumber = DeviceSerialNumber.ToString(); Byte DeviceNameLength = RawMessageDecoded[Cursor]; Cursor++; byte[] DeviceName = new byte[DeviceNameLength]; for(Byte j=0;j<=DeviceNameLength-1;j++) { DeviceName[j] = RawMessageDecoded[Cursor]; Cursor++; } newDevice.Name = System.Text.Encoding.UTF8.GetString(DeviceName); Byte RoomID = RawMessageDecoded[Cursor]; Cursor++; // add the device to the room foreach(Room newRoom in _House.Rooms) { if (newRoom.RoomID == RoomID) { newDevice.AssociatedRoom = newRoom; newRoom.Devices.Add(newDevice.SerialNumber,newDevice); break; } } } #endregion // add this Room to the M_Message-Structure #endregion } else throw new MAXException("Unable to process M Message. Not enough content."); }
/// <summary> /// Inject into an existing get_list_sensors JSON output of an ezcontrol XS1 device /// </summary> public static String Inject_get_list_sensors(String XS1_get_list_sensor_response, House ELVMAXHouse) { Int32 id = 0; Int32 numberofCharactersToDelete = XS1_get_list_sensor_response.IndexOf('('); String Start = XS1_get_list_sensor_response.Remove(numberofCharactersToDelete + 1); String Prepared = XS1_get_list_sensor_response.Remove(0, numberofCharactersToDelete+1); Prepared = Prepared.Remove(Prepared.Length - 4, 4); List<SensorJSON> activeSensors = new List<SensorJSON>(); SensorJSON_Root deserializedSensors = JsonConvert.DeserializeObject<SensorJSON_Root>(Prepared); List<IMAXDevice> devices = ELVMAXHouse.GetAllDevices(); // find first zero sensor foreach(SensorJSON _sensor in deserializedSensors.sensor) { if (_sensor.type != "disabled") activeSensors.Add(_sensor); } id = activeSensors.Count + 1; deserializedSensors.sensor = activeSensors; foreach(IMAXDevice _device in devices) { if (_device.Type == DeviceTypes.HeatingThermostat) { HeatingThermostat heating = (HeatingThermostat)_device; //heating.Temperature SensorJSON _newsensor = new SensorJSON(); if (heating.Temperature == 4.0) { // this heatingthermostat is on "OFF" _newsensor.id = id; id++; _newsensor.name = heating.Name; _newsensor.type = "remotecontrol"; _newsensor.unit = "boolean"; _newsensor.value = 0.0; _newsensor.utime = heating.LastUpdate.JavaScriptTimestampNonMsec(); } else { //this is normal temperature _newsensor.id = id; id++; _newsensor.name = heating.Name; _newsensor.type = "temperature"; _newsensor.unit = "°C"; _newsensor.value = heating.Temperature; _newsensor.utime = heating.LastUpdate.JavaScriptTimestampNonMsec(); } deserializedSensors.sensor.Add(_newsensor); } if (_device.Type == DeviceTypes.ShutterContact) { ShutterContact shutter = (ShutterContact)_device; SensorJSON _newsensor = new SensorJSON(); _newsensor.id = id; id++; _newsensor.name = shutter.Name; _newsensor.type = "dooropen"; _newsensor.unit = "boolean"; _newsensor.utime = shutter.LastUpdate.JavaScriptTimestampNonMsec(); if (shutter.ShutterState == ShutterContactModes.open) _newsensor.value = 1.0; else _newsensor.value = 0.0; deserializedSensors.sensor.Add(_newsensor); } } String SensorJSON = JsonConvert.SerializeObject(deserializedSensors); SensorJSON = Start + SensorJSON + ")"; return SensorJSON; }
public Room(House _House) { AssociatedHouse = _House; Devices = new Dictionary<String,IMAXDevice>(); }
public L_Message(String RAW_Message, House _theHouse, Dictionary<String,IMAXDevice> OutputDeviceList) { DevicesInThisMessage = new List<IMAXDevice>(); if (RAW_Message.Length < 2) throw new MAXException("Unable to process the RAW Message."); if (!RAW_Message.StartsWith("L:")) throw new MAXException("Unable to process the RAW Message. Not a L Message."); RawMessageDecoded = Base64.Decode(RAW_Message.Remove(0,2)); // Tokenize RAW Message List<byte[]> Tokenized = TokenizeMessage.Tokenize(RawMessageDecoded); foreach(byte[] array in Tokenized) { StringBuilder sb = new StringBuilder(); for(int i=0;i<=2;i++) { sb.Append(array[i]); } // get data 1 and data 2 out // on position 5,6 byte Data1 = array[4]; byte Data2 = array[5]; String binValueData1 = Convert.ToString(Data1,2); binValueData1 = binValueData1.PadLeft(8, '0'); String binValueData2 = Convert.ToString(Data2,2); binValueData2 = binValueData2.PadLeft(8, '0'); Int32 Cursor = 7; // the current position, skipping ?1, String RFAddress = sb.ToString(); #region look for this RF Adress in the House's device list List<IMAXDevice> AllDevices = _theHouse.GetAllDevices(); IMAXDevice foundDevice = null; foreach(IMAXDevice _device in AllDevices) { if (_device.RFAddress == RFAddress) { if (_device.Type == DeviceTypes.HeatingThermostat) { foundDevice = new HeatingThermostat(); foundDevice.AssociatedRoom = _device.AssociatedRoom; foundDevice.Name = _device.Name; foundDevice.RFAddress = _device.RFAddress; foundDevice.SerialNumber = _device.SerialNumber; } if (_device.Type == DeviceTypes.ShutterContact) { foundDevice = new ShutterContact(); foundDevice.AssociatedRoom = _device.AssociatedRoom; foundDevice.Name = _device.Name; foundDevice.RFAddress = _device.RFAddress; foundDevice.SerialNumber = _device.SerialNumber; } break; } } #endregion if (foundDevice != null) { // remove the device from the house to add it later again... DevicesInThisMessage.Add(foundDevice); #region HeatingThermostat if (foundDevice.Type == DeviceTypes.HeatingThermostat) { HeatingThermostat KnownDevice = (HeatingThermostat)foundDevice; #region get all those flags out of Data1 and Data2 #region Valid if (binValueData1[3] == '1') KnownDevice.Valid = true; else KnownDevice.Valid = false; #endregion #region Error if (binValueData1[4] == '1') KnownDevice.Error = true; else KnownDevice.Error = false; #endregion #region IsAnswer if (binValueData1[5] == '1') KnownDevice.IsAnswer = true; else KnownDevice.IsAnswer = false; #endregion #region LowBattery if (binValueData2[0] == '1') KnownDevice.LowBattery = true; else KnownDevice.LowBattery = false; #endregion #region LinkError if (binValueData2[1] == '1') KnownDevice.LinkError = true; else KnownDevice.LinkError = false; #endregion #region PanelLock if (binValueData2[2] == '1') KnownDevice.PanelLock = true; else KnownDevice.PanelLock = false; #endregion #region GatewayOK if (binValueData2[3] == '1') KnownDevice.GatewayOK = true; else KnownDevice.GatewayOK = false; #endregion #region Mode String ModeValue = binValueData2[6]+""+binValueData2[7]; switch(ModeValue) { case "00": KnownDevice.Mode = ThermostatModes.automatic; break; case "01": KnownDevice.Mode = ThermostatModes.manual; break; case "10": KnownDevice.Mode = ThermostatModes.vacation; break; case "11": KnownDevice.Mode = ThermostatModes.boost; break; default: break; } #endregion #endregion // hurray, we've got a device we know how to handle B-) ((HeatingThermostat)foundDevice).Temperature = array[Cursor]/2; Cursor++; OutputDeviceList.Add(KnownDevice.SerialNumber,KnownDevice); } #endregion #region ShutterContact if (foundDevice.Type == DeviceTypes.ShutterContact) { ShutterContact KnownDevice = (ShutterContact)foundDevice; #region get all those flags out of Data1 and Data2 #region Valid if (binValueData1[3] == '1') KnownDevice.Valid = true; else KnownDevice.Valid = false; #endregion #region Error if (binValueData1[4] == '1') KnownDevice.Error = true; else KnownDevice.Error = false; #endregion #region IsAnswer if (binValueData1[5] == '1') KnownDevice.IsAnswer = true; else KnownDevice.IsAnswer = false; #endregion #region LowBattery if (binValueData2[0] == '1') KnownDevice.LowBattery = true; else KnownDevice.LowBattery = false; #endregion #region LinkError if (binValueData2[1] == '1') KnownDevice.LinkError = true; else KnownDevice.LinkError = false; #endregion #region PanelLock if (binValueData2[2] == '1') KnownDevice.PanelLock = true; else KnownDevice.PanelLock = false; #endregion #region GatewayOK if (binValueData2[3] == '1') KnownDevice.GatewayOK = true; else KnownDevice.GatewayOK = false; #endregion #region Mode String ModeValue = binValueData2[6]+""+binValueData2[7]; switch(ModeValue) { case "00": KnownDevice.ShutterState = ShutterContactModes.closed; break; case "10": KnownDevice.ShutterState = ShutterContactModes.open; break; default: break; } #endregion #endregion OutputDeviceList.Add(KnownDevice.SerialNumber, KnownDevice); } #endregion } #endregion Constructors #region Properties public MAXMessageType MessageType { get { return MAXMessageType.C; } }
// 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 } }