Page 1 of 1

ELV MAX! Protocol-Reader in PHP

Posted: Sat Oct 29, 2011 6:41 pm
by mega
Hello,
since 2 Days I have this Max-System and worked on a PHP-based-decoder.

To use this script, change the IP to your Cube-IP and get it run on a NAS, HomeServer or XAMPP.
It may also work with portforwarding from the Internet. but that is not tested.

Maybe we get our own webinterface that also can be used on a NAS/Homeserver or so.
To use this script, change the IP to your Cube-IP and get it run on your NAS, HomeServer or XAMPP.
Or use it online, open/forward a port to the cube.

The Script:
http://mega-nas.de/max/

Re: ELV MAX! Protocol-Reader in PHP

Posted: Wed Nov 02, 2011 2:42 pm
by mega
It should now read and decode all known data and puts them in arrays.
Next step is a webinterface to present the data.
Is anyone else working with/on this?

Re: ELV MAX! Protocol-Reader in PHP

Posted: Fri Nov 04, 2011 11:49 am
by wwolkers
I've instlled it on my local server to take a look at it. Works for me, but I haven't had any chance to do anything more with it.

Re: ELV MAX! Protocol-Reader in PHP

Posted: Thu Dec 01, 2011 7:04 pm
by mega
Script is changed to also read the wall-thermostat.

Re: ELV MAX! Protocol-Reader in PHP

Posted: Thu Dec 01, 2011 9:03 pm
by Petr
Hi,
I am thinking about the Max! Cube for my new central heating.
I really like the concept and the thermo-heads with big display and buttons.
But I see all (almost negative or embarrassed) postings here and on the ELV forum and I am little bit sceptical about the functionality.
I have following questions:
  • what is the main goal of the "Max! Cube <=> ELV server" communication protocol recognition (I mean do you think it is possible to use the protocol for our own application to control the Max!Cube?)
  • what about the "Max! Cube <=> EQ3 thermo head" wireless protocol. Are there any attempts to decode and understand it (so it is possible to control it via CUL or CUN see http://www.busware.de for example)?
  • are there any attempts to integrate the Max! with fhem? http://fhem.de/
Regards

Petr

Re: ELV MAX! Protocol-Reader in PHP

Posted: Thu Dec 01, 2011 10:04 pm
by mega
1. With the communication protocol recognition it will be possible to make a own interface or integrate to other interfaces/apps/....
2. this seems to not be needed because the Cube can be used with LAN .
3. not by me, but it should be possible.

You may buy and test the system. some users have problems, others not.

Re: ELV MAX! Protocol-Reader in PHP

Posted: Wed Oct 17, 2012 5:55 pm
by Rainer
I have installed this on my local webserver and it works.
I use firmware 1.3.5 on my max! cube.
The port is not 80 anymore but 62910 works fine.

Has anybody worked a bit on this?
Does anyone know about changing values?

Rainer

Re: ELV MAX! Protocol-Reader in PHP

Posted: Sun Jan 06, 2013 11:36 am
by mega
Here is the complete interface, includes sending:
http://www.mega-nas.de/max/max.zip

This is discontinued! It may not work on newer firmware.

Re: ELV MAX! Protocol-Reader in PHP

Posted: Mon Jan 07, 2013 10:00 am
by ceemjay
Hi Mega

Thanks for your contributions.

I have only just got my MAX! stuff, found this thread yesterday and downloaded your code, so am a real beginner. But what does "This is discontinued!" mean exactly? You are no longer developing it or MAX! has changed in some way??

Thanks
ceemjay

Re: ELV MAX! Protocol-Reader in PHP

Posted: Mon Jan 07, 2013 8:01 pm
by mega
I do not devolop more for that.
Max is too scrap, i now have homematic (since some months)

Re: ELV MAX! Protocol-Reader in PHP

Posted: Mon Nov 10, 2014 12:48 am
by pjakobs
I see that I'm late to the party, but I just bought the Max! stuff. So far, no complaints, but not being able to access it from the shell / through an API was not acceptable. This is why I searched for a scripted solution and found this code. I have started to refactor the reader.php script to ultimately turn it into a RESTful API. Here's my first take on it:

Code: Select all

<?php
// 
// All Max! Commands
//
/*
    DEVICE_LIST = 'L';
    CONFIGURATION = 'C';
    METADATA = 'M';
    
	SET_CREDENTIALS = 'B';
    GET_CREDENTIALS = 'G';
    SET_REMOTEACCESS = 'J';
    SET_USER_DATA = 'P';
    GET_USER_DATA = 'O';
	
    INCOMING_HELLO = "H:";
    INCOMING_FAILURE = "F:";
    INCOMING_DEVICE_LIST = "L:";
    INCOMING_CONFIGURATION = "C:";
    INCOMING_METADATA = "M:";
    INOMING_NEW_DEVICE = "N:";
    INCOMING_ACKNOWLEDGE = "A:";
    INCOMING_ENCRYPTION = "E:";
    INCOMING_DECRYPTION = "D:";
    INCOMING_SET_CREDENTIALS = "b:";
    INCOMING_GET_CREDENTIALS = "g:";
    INCOMING_SET_REMOTEACCESS = "j:";
    INCOMING_SET_USER_DATA = "p:";
    INCOMING_GET_USER_DATA = "o:";
    INCOMING_SEND_DEVICE_CMD = "S:";

    OUTGOING_URL = "u:";
    OUTGOING_INTERVAL = "i:";
    OUTGOING_SEND = "s:";
    OUTGOING_METADATA = "m:";
    OUTGOING_INCLUSION_MODE = "n:";
    OUTGOING_CANCEL_INCLUSION_MODE = "x:";
    OUTGOING_MORE_DATA = "g:";
    OUTGOING_QUIT = "q:";
    OUTGOING_ENCRYPTION = "e:";
    OUTGOING_DECRYPTION = "d:";
    OUTGOING_SET_CREDENTIALS = "B:";
    OUTGOING_GET_CREDENTIALS = "G:";
    OUTGOING_SET_REMOTEACCESS = "J:";
    OUTGOING_SET_USER_DATA = "P:";
    OUTGOING_GET_USER_DATA = "O:";
    OUTGOING_SEND_DEVICE_CMD = "s:";
    OUTGOING_RESET = "a:";
    OUTGOING_RESET_ERROR = "r:";
    OUTGOING_DELETE_DEVICES = "t:";
    OUTGOING_SET_PUSHBUTTON_CONFIG = "w:";
    OUTGOING_GET_DEVICE_LIST = "l:";
    OUTGOING_SET_URL = "u:";
    OUTGOING_GET_CONFIGURATION = "c:";
    OUTGOING_TIME_CONFIG = "v:";
    OUTGOING_SEND_WAKEUP = "z:";
*/

//
// Max! Date encoding
//
/*
    9D0B    1001110100001011
            MMMDDDDDM YYYYYY
            100     0        = 1000b  = 8d  = month
               11101         = 11101b = 29d = day
                      001011 = 1011b  = 11d = year-2000                   

    868B    1000011010001011
            MMMDDDDDM YYYYYY
            100     1         1001b = 9d  = month
               00110           110b = 6d  = day
                      001011  1011b = 11d = year-2000
*/
echo "<pre>";

// Uncomment the follwing 2 lines
$host = "192.168.35.64"; // Your Cube-IP or hostame Here!
$port = "62910";


//
// open connection
//
$fp = @fsockopen($host, $port, $errno, $errstr, 5);

if (!$fp)
{
	switch($errno)
	{
		case 111:
			die("Local software running - ".$errstr);
			break;
		case 113:
			die("No Connection - ".$errstr);
			break;
		default:
			die("Connection error - ".$errno." - ".$errstr);
			break;
	}
}

socket_set_blocking($fp,false);
sleep(1);
$finished = 0;
$now = time();

//
// read from cube
//
$buff = "";
while (!feof($fp) && time() < $now+20 && $finished == 0)
{
	$line = fgets($fp);
	if (strpos($line,"L:") !== false) $finished = 1;
	if ($line != "")  $buff .= $line."\n";
	//sleep(1);
}
fclose($fp);

//
// fail 
//
if ($finished != 1) die("Could not find an L record");

ob_start();

$arr = explode("\n\n",$buff);
print_r($arr);
echo '<hr />';
foreach ($arr as $v)
{
	$p_type=substr($v,0,2); //packet type
	switch($p_type)
	{
		case "H:":
		/*
			Initial "Hello"
			
			H:KHA0008979,0744a8,0113,00000000,576c1768,18,32,0e0b09,0a08,03,0000
			
			IEQ0123456  Serial number
			00b3b4      RF address, hexadecimal
			0102        Firmware version, 1.0.2
			00000000    ?
			355df98a    ?
			03          ?
			32          ?
		*/
			$arr2 = explode(',',substr($v,2,strlen($v)));
			//$str = base64_decode($arr2[2]);
		
			$data["sys"]["SerialNumber"] = $arr2[0];
			$data["sys"]["RFAdress"] = $arr2[1];
			$data["sys"]["Firmware"] = $arr2[2];
			$data["sys"]["1?"] = $arr2[3]; //00000000
			$data["sys"]["HTTP-ConnID"] = $arr2[4];
			$data["sys"]["2?"] = $arr2[5];
			$data["sys"]["3?"] = $arr2[6]; //31 
			$data["sys"]["Date"] = hexdec(substr($arr2[7],4,2)).".".hexdec(substr($arr2[7],2,2)).".".hexdec(substr($arr2[7],0,2));
			$data["sys"]["Time"] = hexdec(substr($arr2[8],0,2)).":".hexdec(substr($arr2[8],2,2));
			$data["sys"]["Timestamp"] = mktime(hexdec(substr($arr2[8],0,2)),hexdec(substr($arr2[8],2,2)),0,hexdec(substr($arr2[7],2,2)),hexdec(substr($arr2[7],4,2)),hexdec(substr($arr2[7],0,2)));
		break;
		
		case "M:":
		/*
			Metadata
			
			M:00,01,VgICAQVCw7xybwx6FQIKV29obnppbW1lcgx6PgUDDM8AS0VRMDgwODIzOBBXYW5kdGhlcm1vc3RhdCAxAQEMehVLRVEwNzIwMDA4EkhlaXprw7ZycGVyIHJlY2h0cwEBDHo+S0VRMDcxOTk2OAtIZWl6a8O2cnBlcgIEDK83S0VRMDg0MTI2NA5GZW5zdGVyIHJlY2h0cwEEDLI1S0VRMDg0MjExMgdGZW5zdGVyAgE=
			
			00000000  56 02 02 01 05 42 c3 bc  72 6f 0c 7a 15 02 0a 57  |V....B..ro.z...W|
			00000010  6f 68 6e 7a 69 6d 6d 65  72 0c 7a 3e 05 03 0c cf  |ohnzimmer.z>....|
			00000020  00 4b 45 51 30 38 30 38  32 33 38 10 57 61 6e 64  |.KEQ0808238.Wand|
			00000030  74 68 65 72 6d 6f 73 74  61 74 20 31 01 01 0c 7a  |thermostat 1...z|
			00000040  15 4b 45 51 30 37 32 30  30 30 38 12 48 65 69 7a  |.KEQ0720008.Heiz|
			00000050  6b c3 b6 72 70 65 72 20  72 65 63 68 74 73 01 01  |k..rper rechts..|
			00000060  0c 7a 3e 4b 45 51 30 37  31 39 39 36 38 0b 48 65  |.z>KEQ0719968.He|
			00000070  69 7a 6b c3 b6 72 70 65  72 02 04 0c af 37 4b 45  |izk..rper....7KE|
			00000080  51 30 38 34 31 32 36 34  0e 46 65 6e 73 74 65 72  |Q0841264.Fenster|
			00000090  20 72 65 63 68 74 73 01  04 0c b2 35 4b 45 51 30  | rechts....5KEQ0|
			000000a0  38 34 32 31 31 32 07 46  65 6e 73 74 65 72 02 01  |842112.Fenster..|
			000000b0

			0001 56 -> ?
			0002 02 -> ?
			0003 02 -> RoomCount
		
			0004 01 -> RoomID
			0005 05 -> RoomNameLength
			0006 42 C3 BC 72 6F -> RoomName
			000A 0C 7A 15 -> RF Address
			
			000D 02 -> RoomID
			000E 0A -> RoomNameLength
			000F 57 6F 68 6E 7A 69 6D 6D 65 72 -> RoomName
			0018 0C 7A 3E -> RF Address
			
			OO1B 05
			
			Room:
			Description        Startpos    Length      Example Value
			=====================================================================
			Room id            00          1           1
			Room name length   01          1           0A
			Room name          02          variable    Hobbykamer
			Address(?)                     3           003508
			
			Device:
			Description        Startpos    Length      Example Value
			=====================================================================
			Device type        00          1           1
			Address            01          3           003508
			Serial Number      04          10          IEQ0109125
			Name length        0E          1           0C
			Name               0F          variable    Thermostat 1
			Room id                        1           01
		*/
			
			 $arr2 = explode(',',$v);
			 $str = base64_decode($arr2[2]);

			echo $arr2[0].','.$arr2[1]."\n".htmlentities($str)."\n";
			for($i = 0 ; $i <= strlen($str) ; $i++) 
			{
				echo dechex(ord(substr($str,$i,1)))." ";
			}
			echo "\n";

			$pos = 0;
			$readlen =  1; 
			$data["meta"]["?1"] = dechex(ord(substr($str,$pos,$readlen)))."";  
			$pos += $readlen;
			
			$readlen =  1; 
			$data["meta"]["?2"] = dechex(ord(substr($str,$pos,$readlen)))."";  
			$pos += $readlen; 
			
			$readlen =  1; 
			$data["meta"]["RoomCount"] = dechex(ord(substr($str,$pos,$readlen)))."";  
			$pos += $readlen;

			for($j = 1 ; $j <= $data["meta"]["RoomCount"] ; $j++)
			{
				$readlen = 1;
				$RoomID = dechex(ord(substr($str,$pos,$readlen)))."";
				$data["rooms"][$RoomID]["RoomID"] = $RoomID;  
				$pos += $readlen;
				
				$readlen = 1;
				$data["rooms"][$RoomID]["RoomNameLength"] = ord(substr($str,$pos,$readlen)).""; 
				$pos += $readlen;
				
				$readlen = $data["rooms"][$RoomID]["RoomNameLength"]; 
				$data["rooms"][$RoomID]["RoomName"] = htmlentities(substr($str,$pos,$readlen))."";
				$pos += $readlen;
				
				$readlen = 3;
				for($i = $pos; $i < $readlen+$pos ; $i++)
				{
					$data["rooms"][$RoomID]["RFAdress(?)"] .= str_pad(dechex(ord(substr($str,$i,1))),2,"0",STR_PAD_LEFT).""; 
				}
				$pos += $readlen;
			}
			
			$readlen = 1; 
			$data["meta"]["DevCount"] = dechex(ord(substr($str,$pos,$readlen))).""; 
			$pos += $readlen;
			/*
			00000010  6f 68 6e 7a 69 6d 6d 65  72 0c 7a 3e 05 03 0c cf  |ohnzimmer.z>....|
			00000020  00 4b 45 51 30 38 30 38  32 33 38 10 57 61 6e 64  |.KEQ0808238.Wand|
			00000030  74 68 65 72 6d 6f 73 74  61 74 20 31 01 01 0c 7a  |thermostat 1...z|
			00000040  15 4b 45 51 30 37 32 30  30 30 38 12 48 65 69 7a  |.KEQ0720008.Heiz|
			00000050  6b c3 b6 72 70 65 72 20  72 65 63 68 74 73 01 01  |k..rper rechts..|
			00000060  0c 7a 3e 4b 45 51 30 37  31 39 39 36 38 0b 48 65  |.z>KEQ0719968.He|
			00000070  69 7a 6b c3 b6 72 70 65  72 02 04 0c af 37 4b 45  |izk..rper....7KE|
			00000080  51 30 38 34 31 32 36 34  0e 46 65 6e 73 74 65 72  |Q0841264.Fenster|
			00000090  20 72 65 63 68 74 73 01  04 0c b2 35 4b 45 51 30  | rechts....5KEQ0|
			000000a0  38 34 32 31 31 32 07 46  65 6e 73 74 65 72 02 01  |842112.Fenster..|
			
			
			0C  05 -> DevCount
			0D  03 -> DevType
			0E  0C CF 00 -> RFAddress
			21  4B 45 51 30 38 30 38 32 33 38 -> SerialNumber
			2B  10 -> NameLength
			2C  57 61 6E 64 74 68 65 72 6D 6F 73 74 61 74 20 31 -> DeviceName
			3C  01 -> RoomID
			
			*/
			
			for($j = 1 ; $j <= $data["meta"]["DevCount"]; $j++)
			{
				unset($hilf);
				
				$readlen = 1; 
				$hilf["DeviceType"] = dechex(ord(substr($str,$pos,$readlen))).""; 
				$pos += $readlen;
				
				$readlen = 3; 
				for($i = $pos; $i < $readlen+$pos ; $i++) 
				{
					$hilf["RFAdress"] .= str_pad(dechex(ord(substr($str,$i,1))),2,"0",STR_PAD_LEFT).""; 
				}
				$pos += $readlen; 
				
				$readlen = 10; 
				$hilf["SerialNumber"] .= htmlentities(substr($str,$pos,$readlen)).""; 
				$pos += $readlen;
				
				$readlen = 1; 
				$hilf["NameLength"] = ord(substr($str,$pos,$readlen)).""; 
				$pos += $readlen; 
				//echo "debug === Device Name Length:".$hilf["NameLength"]."\n";
				
				$readlen = $hilf["NameLength"]; 
				$hilf["Name"] = htmlentities(substr($str,$pos,$readlen))."";
				$pos += $readlen;
				//echo "debug === Device Name:".$hilf["Name"]."\n";
				
				$readlen = 1; 
				$hilf["RoomID"] = dechex(ord(substr($str,$pos,1))).""; 
				$pos += $readlen;

				$data["rooms"][$hilf["RoomID"]]["Devices"][$j]["DeviceType"] = $hilf["DeviceType"];
				$data["rooms"][$hilf["RoomID"]]["Devices"][$j]["RFAdress"] = $hilf["RFAdress"];
				$data["rooms"][$hilf["RoomID"]]["Devices"][$j]["SerialNumber"] = $hilf["SerialNumber"];
				$data["rooms"][$hilf["RoomID"]]["Devices"][$j]["NameLength"] = $hilf["NameLength"];
				$data["rooms"][$hilf["RoomID"]]["Devices"][$j]["Name"] = $hilf["Name"];
				$data["rooms"][$hilf["RoomID"]]["Devices"][$j]["RoomID"] = $hilf["RoomID"];
			}
		break;		
		case "C:":
		/*
			Configuration
			
			C:0744a8,7QdEqAATAQBLSEEwMDA4OTc5AAsABEAAAAAAAAAAAP///////////////////////////wsABEAAAAAAAAAAQf///////////////////////////2h0dHA6Ly9tYXgtcG9ydGFsLmVxLTMuZGU6ODAvbG9va3VwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAENFVAAACgADAAAOEENFU1QAAwACAAAcIA==
			
			00000000  ed 07 44 a8 00 13 01 00  4b 48 41 30 30 30 38 39  |..D.....KHA00089|
			00000010  37 39 00 0b 00 04 40 00  00 00 00 00 00 00 00 ff  |79....@.........|
			00000020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
			00000030  ff ff ff ff 0b 00 04 40  00 00 00 00 00 00 00 41  |.......@.......A|
			00000040  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
			00000050  ff ff ff ff ff 68 74 74  70 3a 2f 2f 6d 61 78 2d  |.....http://max-|
			00000060  70 6f 72 74 61 6c 2e 65  71 2d 33 2e 64 65 3a 38  |portal.eq-3.de:8|
			00000070  30 2f 6c 6f 6f 6b 75 70  00 00 00 00 00 00 00 00  |0/lookup........|
			00000080  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
			*
			000000d0  00 00 00 00 00 00 43 45  54 00 00 0a 00 03 00 00  |......CET.......|
			000000e0  0e 10 43 45 53 54 00 03  00 02 00 00 1c 20        |..CEST....... |
			000000ee
			
			003508        RF address of the device
			
			Start Length  Value       Description
			==================================================================
			00         1  D2          Length of data: D2 = 210(decimal) = 210 bytes
			01         3  003508      RF address
			04         1  01          Device Type
			05         3  0114FF      ?
			08        10  IEQ0109125  Serial Number       
			12         1  28          Comfort Temperature     
			13         1  28          Eco Temperature         
			14         1  3D          MaxSetPointTemperature 
			15         1  09          MinSetPointTemperature 
			16         1  07          Temperature Offset * 2
									  The default value is 3,5, which means the offset = 0 degrees.
									  The offset is adjustable between -3,5 and +3,5 degrees,
									  which results in a value in this response between 0 and 7 (decoded already)       
			17         1  28          Window Open Temperature   
			18         1  03          Window  Open Duration     
			19         1  30          Boost Duration and Boost Valve Value
									  The 3 MSB bits gives the duration, the 5 LSB bits the Valve Value%.
									  Duration: With 3 bits, the possible values (Dec) are 0 to 7, 0 is not used.
									  The duration in Minutes is: if Dec value = 7, then 30 minutes, else Dec value * 5 minutes
									  Valve Value: dec value 5 LSB bits * 5 gives Valve Value in %
			1A         1  0C          Decalcification: Day of week and Time
									  In bits: DDDHHHHH
									  The three most significant bits (MSB) are presenting the day, Saturday = 1, Friday = 7
									  The five least significant bits (LSB) are presenting the time (in hours)     
			1B         1  FF          Maximum Valve setting; *(100/255) to get in %
			1C         1  00          Valve Offset ; *(100/255) to get in %
			1D         ?  44 48 ...   Weekly program (see The weekly program)
		*/


			$arr2 = explode(',',$v);
			$str = base64_decode($arr2[1]);
			echo $arr2[0]."\n".htmlentities($str)."\n";
			for($i = 0 ; $i <= strlen($str) ; $i++) echo dechex(ord(substr($str,$i,1)))." ";
			echo "\n";
			echo "\n";
			echo strlen($str)."\n";

			unset($hilf);

			$pos = 0;
			$readlen = 1; 
			$hilf["?1"] = dechex(ord(substr($str,$pos,1)))."";  
			$pos += $readlen;
			
			$readlen = 3; 
			for($i = $pos; $i < $readlen+$pos ; $i++) 
			{
				$hilf["RFAdress"] .= str_pad(dechex(ord(substr($str,$i,1))),2,"0",STR_PAD_LEFT)."";  
			}
			$pos += $readlen;
			
			$readlen = 1; 
			$hilf["DeviceType"] = dechex(ord(substr($str,$pos,1)))."";  
			$pos += $readlen;
			
			$readlen = 3; 
			for($i = $pos; $i < $readlen+$pos ; $i++) 
			{
				$hilf["?2"] .= dechex(ord(substr($str,$i,1)))." ";  
			}
			$pos += $readlen;
			
			$readlen = 10; 
			$hilf["SerialNumber"] = htmlentities(substr($str,$pos,$readlen))."";  
			$pos += $readlen;

			$deviceconf[$hilf["RFAdress"]]["?1"] = $hilf["?1"];
			$deviceconf[$hilf["RFAdress"]]["RFAdress"] = $hilf["RFAdress"];
			$deviceconf[$hilf["RFAdress"]]["DeviceType"] = $hilf["DeviceType"];
			$deviceconf[$hilf["RFAdress"]]["?2"] = $hilf["?2"];
			$deviceconf[$hilf["RFAdress"]]["SerialNumber"] = $hilf["SerialNumber"];


			switch($deviceconf[$hilf["RFAdress"]]["DeviceType"])
			{
				case "0":
					// Cube
					$readlen = 1;
					$deviceconf[$hilf["RFAdress"]]["PortalEnabled"] = ord(substr($str,$i,$readlen))."";  
					$pos += $readlen;
					
					$readlen =  4; 
					for($i = $pos; $i < $readlen+$pos ; $i++) 
					{
						$deviceconf[$hilf["RFAdress"]]["?3"] .= dechex(ord(substr($str,$i,1)))." ";
					}
					$pos += $readlen;
					
					$readlen =  8; 
					for($i = $pos; $i < $readlen+$pos ; $i++) 
					{
						$deviceconf[$hilf["RFAdress"]]["?4"] .= dechex(ord(substr($str,$i,1)))." ";  
					}
					$pos += $readlen;
					
					$readlen = 21; 
					for($i = $pos; $i < $readlen+$pos ; $i++) 
					{
						$deviceconf[$hilf["RFAdress"]]["?5"] .= dechex(ord(substr($str,$i,1)))." ";  
					}
					$pos += $readlen;
					
					$readlen = 4; 
					for($i = $pos; $i < $readlen+$pos ; $i++)
					{
						$deviceconf[$hilf["RFAdress"]]["?6"] .= dechex(ord(substr($str,$i,1)))." ";  
					}
					$pos += $readlen;
					
					$readlen =  8; 
					for($i = $pos; $i < $readlen+$pos ; $i++) 
					{
						$deviceconf[$hilf["RFAdress"]]["?7"] .= dechex(ord(substr($str,$i,1)))." ";  
					}
					$pos += $readlen;
					
					$readlen = 21; 
					for($i = $pos; $i < $readlen+$pos ; $i++) 
					{
						$deviceconf[$hilf["RFAdress"]]["?8"] .= dechex(ord(substr($str,$i,1)))." ";  
					}
					$pos += $readlen;

					$readlen = 36; 
					$deviceconf[$hilf["RFAdress"]]["PortalURL"] .= htmlentities(substr($str,$i,$readlen))."";
					$pos += $readlen;

					$readlen = 60; for($i = $pos; $i < $readlen+$pos ; $i++) $deviceconf[$hilf["RFAdress"]]["?9"] .= ord(substr($str,$i,1))." ";  $pos += $readlen;
					$readlen = 33; for($i = $pos; $i < $readlen+$pos ; $i++) $deviceconf[$hilf["RFAdress"]]["?A"] .= ord(substr($str,$i,1))." ";  $pos += $readlen;
					$readlen =  3; for($i = $pos; $i < $readlen+$pos ; $i++) $deviceconf[$hilf["RFAdress"]]["StandardTimeZone"] .= htmlentities(substr($str,$i,1))."";  $pos += $readlen;
					$readlen =  9; for($i = $pos; $i < $readlen+$pos ; $i++) $deviceconf[$hilf["RFAdress"]]["?C"] .= ord(substr($str,$i,1))." ";  $pos += $readlen;
					$readlen =  4; for($i = $pos; $i < $readlen+$pos ; $i++) $deviceconf[$hilf["RFAdress"]]["DSTTimeZone"] .= htmlentities(substr($str,$i,1))."";  $pos += $readlen;
					$readlen =  9; for($i = $pos; $i < $readlen+$pos ; $i++) $deviceconf[$hilf["RFAdress"]]["?E"] .= ord(substr($str,$i,1))." ";  $pos += $readlen;
				break;
				case "1":
					// Thermostat
					$readlen =  1; $deviceconf[$hilf["RFAdress"]]["ComfortTemperature"] = (ord(substr($str,$pos,$readlen))/2)."";  $pos += $readlen; 
					$readlen =  1; $deviceconf[$hilf["RFAdress"]]["EcoTemperature"] = (ord(substr($str,$pos,$readlen))/2)."";  $pos += $readlen;
					$readlen =  1; $deviceconf[$hilf["RFAdress"]]["MaxSetPointTemperature"] = (ord(substr($str,$pos,$readlen))/2)."";  $pos += $readlen;
					$readlen =  1; $deviceconf[$hilf["RFAdress"]]["MinSetPointTemperature"] = (ord(substr($str,$pos,$readlen))/2)."";  $pos += $readlen;
					$readlen =  1; $deviceconf[$hilf["RFAdress"]]["TemperatureOffset"] = (ord(substr($str,$pos,$readlen)))/2-3.5."";  $pos += $readlen;
					$readlen =  1; $deviceconf[$hilf["RFAdress"]]["WindowOpenTemperature"] = (ord(substr($str,$pos,$readlen))/2)."";  $pos += $readlen;
					$readlen =  1; $deviceconf[$hilf["RFAdress"]]["WindowOpenDuration"] = dechex(ord(substr($str,$pos,$readlen)))."";  $pos += $readlen;
					$readlen =  1; $deviceconf[$hilf["RFAdress"]]["Boost"] = str_pad(decbin(ord(substr($str,$pos,$readlen))),8,"0",STR_PAD_LEFT)."";  $pos += $readlen;
					$deviceconf[$hilf["RFAdress"]]["BoostDuration"] = bindec(substr($deviceconf[$hilf["RFAdress"]]["Boost"],0,3))*5;
					$deviceconf[$hilf["RFAdress"]]["BoostValue"] = bindec(substr($deviceconf[$hilf["RFAdress"]]["Boost"],3,5))*5;

					$readlen =  1; $deviceconf[$hilf["RFAdress"]]["Decalc"] = str_pad(decbin(ord(substr($str,$pos,$readlen))),8,"0",STR_PAD_LEFT)."";  $pos += $readlen;
					$deviceconf[$hilf["RFAdress"]]["DecalcDay"] = bindec(substr($deviceconf[$hilf["RFAdress"]]["Decalc"],0,3));
					$deviceconf[$hilf["RFAdress"]]["DecalcTime"] = bindec(substr($deviceconf[$hilf["RFAdress"]]["Decalc"],3,5));
					$readlen =  1; $deviceconf[$hilf["RFAdress"]]["MaximumValveSetting"] = dechex(ord(substr($str,$pos,$readlen)))*(100/255)."";  $pos += $readlen;
					$readlen =  1; $deviceconf[$hilf["RFAdress"]]["ValveOffset"] = dechex(ord(substr($str,$pos,$readlen)))*(100/255)."";  $pos += $readlen;

					for ($j = 1 ; $j <= 7 ; $j++)
					{
						$readlen = 26;// Sat, Sun, Mon, Tue, Weg, Thu, Fri
						for($i = $pos; $i < $readlen+$pos ; $i+=2)
						{
							$bin  = str_pad(decbin(hexdec(dechex(ord(substr($str,$i,1))))),8,"0",STR_PAD_LEFT).str_pad(decbin(hexdec(dechex(ord(substr($str,$i+1,1))))),8,"0",STR_PAD_LEFT);
							//echo $bin."  ";
							$deg = bindec(substr($bin,0,7));
							//$deviceconf[$hilf["RFAdress"]]["WeeklyProgramm".$j.""] .= ($deg/2)."^C ";
							$min = bindec(substr($bin,7,9));
							//$deviceconf[$hilf["RFAdress"]]["WeeklyProgramm".$j.""] .= number_format(($min*5/60),2)."hr | ";
							$deviceconf[$hilf["RFAdress"]]["WeeklyProgramm".$j."deg"][] = ($deg/2);
							$deviceconf[$hilf["RFAdress"]]["WeeklyProgramm".$j."time"][] = number_format(($min*5/60),2);
						}
					$pos += $readlen;
					}
				break;
				case "4":
					// Fensterkontakt
					echo "======debug======";echo $hilf["?2"];
					$deviceconf[$hilf["RFAdress"]]["WindowOpen"] = $hilf["?2"]&&0b00000010;
				break;
			}
		break;
		
		case "L:":
		/*
			Device List
			
			L:DAzPAPkSGAQqAAAA1gsMehX5EhgAKgAAAAsMej7sEhgKKgAAAAYMrzfsEhAGDLI1bBIQ
			
			00000000  0c 0c cf 00 f9 12 18 04  2a 00 00 00 d6 0b 0c 7a  |........*......z|
			00000010  15 f9 12 18 00 2a 00 00  00 0b 0c 7a 3e ec 12 18  |.....*.....z>...|
			00000020  0a 2a 00 00 00 06 0c af  37 ec 12 10 06 0c b2 35  |.*......7......5|
			00000030  6c 12 10                                          |l..|
			00000033
			
			Start Length  Value       Description
			==================================================================
			0          1  0B          Length of data: 0B = 11(decimal) = 11 bytes
			1          3  003508      RF address
			4          1  00          ?
			5          1  12          bit 4     Valid              0=invalid;1=information provided is valid
									  bit 3     Error              0=no; 1=Error occurred
									  bit 2     Answer             0=an answer to a command,1=not an answer to a command
									  bit 1     Status initialized 0=not initialized, 1=yes
										   
									  12  = 00010010b
										  = Valid, Initialized
									 
			6       1     1A          bit 7     Battery       1=Low
									  bit 6     Linkstatus    0=OK,1=error
									  bit 5     Panel         0=unlocked,1=locked
									  bit 4     Gateway       0=unknown,1=known
									  bit 3     DST setting   0=inactive,1=active
									  bit 2     Not used
									  bit 1,0   Mode         00=auto/week schedule
															 01=Manual
															 10=Vacation
															 11=Boost   
									  1A  = 00011010b
										  = Battery OK, Linkstatus OK, Panel unlocked, Gateway known, DST active, Mode Vacation.
			7       1     20          Valve position in %
			8       1     2C          Temperature setpoint, 2Ch = 44d; 44/2=22 deg. C
			9       2     858B        Date until (05-09-2011) (see Encoding/Decoding date/time)
			B       1     2E          Time until (23:00) (see Encoding/Decoding date/time)
		*/
			$v = substr($v,2,strlen($v));
			$str = base64_decode($v);

			//echo htmlentities($str)."\n";
			//$buff = "";
			//for($i = 0 ; $i <= strlen($str) ; $i++) $buff .= dechex(ord(substr($str,$i,1)))." ";
			//$buff .= "\n";
			//echo $buff;

			$pos = 0;

			for($j = 1 ; $j <= $data["meta"]["DevCount"]; $j++)
			{
				unset($hilf);
				$readlen =              1; $hilf["ReadLength"] = htmlentities(ord(substr($str,$pos,1))).""; $pos += $readlen;
				$readlen =              3; for($i = $pos; $i < $readlen+$pos ; $i++) $hilf["RFAdress"] .= str_pad(dechex(ord(substr($str,$i,1))),2,"0",STR_PAD_LEFT).""; $pos += $readlen;
				$readlen =              1; $hilf["?1"] = dechex(ord(substr($str,$pos,1))).""; $pos += $readlen;
				$readlen =              1; $hilf["Data1"] .= str_pad(decbin(ord(substr($str,$pos,1))),8,"0",STR_PAD_LEFT).""; $pos += $readlen;
				$readlen =              1; $hilf["Data2"] .= str_pad(decbin(ord(substr($str,$pos,1))),8,"0",STR_PAD_LEFT).""; $pos += $readlen;
				if($hilf["ReadLength"] == 11)	
				{
					$readlen =              1; $hilf["?2"] = dechex(ord(substr($str,$pos,1))).""; $pos += $readlen;
					$readlen =              1; $hilf["Temperature"] = (ord(substr($str,$pos,1))/2).""; $pos += $readlen;
					$readlen =              2; for($i = $pos; $i < $readlen+$pos ; $i++) $hilf["DateUntil"] .= str_pad(decbin(ord(substr($str,$i,1))),8,"0",STR_PAD_LEFT).""; $pos += $readlen;
					$readlen =              1; $hilf["TimeUntil"] = (ord(substr($str,$pos,1))*0.5).""; $pos += $readlen;
				}

				$deviceconf[$hilf["RFAdress"]]["LiveReadLength"] = $hilf["ReadLengt	h"];
				$deviceconf[$hilf["RFAdress"]]["LiveRFAdress"] = $hilf["RFAdress"];
				$deviceconf[$hilf["RFAdress"]]["Live?1"] = $hilf["?1"];
				if($hilf["ReadLength"] == 11)
				{
					$deviceconf[$hilf["RFAdress"]]["Live?2"] = $hilf["?2"];
					$deviceconf[$hilf["RFAdress"]]["Temperature"] = $hilf["Temperature"];
					$deviceconf[$hilf["RFAdress"]]["DateUntil"] = $hilf["DateUntil"];
					$year = substr($hilf["DateUntil"],-6,6);
					$month = substr($hilf["DateUntil"],0,3).substr($hilf["DateUntil"],8,1);
					$day = substr($hilf["DateUntil"],3,5);
					$deviceconf[$hilf["RFAdress"]]["DateUntil"] = bindec($day).".".bindec($month).".".bindec($year);
					$deviceconf[$hilf["RFAdress"]]["TimeUntil"] = $hilf["TimeUntil"];
					$deviceconf[$hilf["RFAdress"]]["TimestampUntil"] = mktime(floor($hilf["TimeUntil"]),($hilf["TimeUntil"]-floor($hilf["TimeUntil"]))*60,0,bindec($month),bindec($day),bindec($year));
				}

				$deviceconf[$hilf["RFAdress"]]["valid"] = substr($hilf["Data1"],3,1);
				$deviceconf[$hilf["RFAdress"]]["Error"] = substr($hilf["Data1"],4,1);
				$deviceconf[$hilf["RFAdress"]]["isAnswer"] = substr($hilf["Data1"],5,1);
				$deviceconf[$hilf["RFAdress"]]["initialized"] = substr($hilf["Data1"],6,1);
				$deviceconf[$hilf["RFAdress"]]["LiveData7"] = substr($hilf["Data1"],7,1);

				$deviceconf[$hilf["RFAdress"]]["LowBatt"] = substr($hilf["Data2"],0,1);
				$deviceconf[$hilf["RFAdress"]]["LinkError"] = substr($hilf["Data2"],1,1);
				$deviceconf[$hilf["RFAdress"]]["PanelLock"] = substr($hilf["Data2"],2,1);
				$deviceconf[$hilf["RFAdress"]]["GatewayOK"] = substr($hilf["Data2"],3,1);
				$deviceconf[$hilf["RFAdress"]]["DST"] = substr($hilf["Data2"],4,1);
				$deviceconf[$hilf["RFAdress"]]["Not used"] = substr($hilf["Data2"],5,1);
				switch (substr($hilf["Data2"],6,2))
				{
					case "00" : $deviceconf[$hilf["RFAdress"]]["Mode"] = "auto"; break;
					case "01" : $deviceconf[$hilf["RFAdress"]]["Mode"] = "manu"; break;
					case "10" : $deviceconf[$hilf["RFAdress"]]["Mode"] = "vacation"; break;
					case "11" : $deviceconf[$hilf["RFAdress"]]["Mode"] = "boost"; break;
				}
				$deviceconf[$hilf["RFAdress"]]["LiveDataX"] = $hilf["Data3"];
				echo "\n";
			}
		break;
	}
}

if (basename($_SERVER['SCRIPT_FILENAME']) != "interface.php")
{
$ob = ob_get_contents(); 
ob_end_clean();
echo $ob;
print_r($data);
echo "\n<hr />\n";
print_r($deviceconf);
}
ob_end_clean();

echo "</pre>";
?>