General
The ELV MAX! protocol is used to communicate with the ELV MAX! Cube LAN Gateway. This is the interface to the range of MAX! products. The MAX! Cube LAN Gateway is equipped with a USB connection for power and a RJ-45 Ethernet connection to connect it to your local LAN/router. The MAX! Cube LAN Gateway uses bi-directional radio communication to query the status of the other MAX! components and configure them. The other MAX! components can also function independently, without the MAX! Cube LAN Gateway. (which will be called 'Cube' from now on)
All MAX! components have a serial number. On the Cube this serial number can be found on the bottom and has the format IEQxxxxxx. The serial number of the Radiator Thermostat can be found on the inside of the battery compartment.
When a TCP/IP connection is being made to port 80 of the Cube, it starts sending H, M and C responses. These responses contain detailed information about the configuration of the Cube and all the other MAX! components that are teached-in. All responses encountered so far start with a character followed by a colon (:). The responses always end (so far) with a Carriage Return (CR, 0x0D, $0D, chr(13)) and a Line Feed (LF, 0x0A, $0A, chr(10)). Some parts of the response data is Base64 encoded; Base64 is a very common encoding scheme for transferring binary data by only using prinable characters. See http://en.wikipedia.org/wiki/Base64 for more information. Where applicable the examples in this post will be presented in Base64 encoded (e.g. as received from the Cube) and in binary/hex view format for easy reading. When the term payload is used, the part after the colon is meant.
H response ("Incoming Hello")
The H response contains information about the Cube.
An example:
H:IEQ0123456,00b3b4,0102,00000000,355df98a,03,32
The payload can be split on the comma character in several parts:
Code: Select all
IEQ0123456 Serial number
00b3b4 RF address, hexadecimal
0102 Firmware version, 1.0.2
00000000 ?
355df98a ?
03 ?
32 ?
The M response contains information about additional data, like the Rooms that are defined, the Devices and the names they were given, and how the rooms and Devices are linked to each other.
Example:
M:00,01,VgIBAQpIb2JieWthbWVyADUIAQEANQhJRVEwMTA5MTI1DFRoZXJtb3N0YXQgMQEB
Decoded:
Code: Select all
00: 56 02 01 01 0A 48 6F 62 62 79 6B 61 6D 65 72 00 | V....Hobbykamer.
10: 35 08 01 01 00 35 08 49 45 51 30 31 30 39 31 32 | 5....5.IEQ010912
20: 35 0C 54 68 65 72 6D 6F 73 74 61 74 20 31 01 01 | 5.Thermostat 1..
A room has the following structure:
Code: Select all
Description Startpos Length Example Value
=====================================================================
Room id 00 1 1
Room name length 01 1 0A
Room name 02 variable Hobbykamer
Address(?) 3 003508
Code: Select all
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
C response ("Configuration")
The C response contains information about the configuration of a device.
Example:
C:003508,0gA1CAEBFP9JRVEwMTA5MTI1KCg9CQcoAzAM/wBESFUIRSBFIEUgRSBFIEUgRSBFIEUgRSBFIERIVQhFIEUgRSBFIEUgRSBFIEUgRSBFIEUg
REhUbETMVRRFIEUgRSBFIEUgRSBFIEUgRSBESFRsRMxVFEUgRSBFIEUgRSBFIEUgRSBFIERIUmxEzFUURSBFIEUgRSBFIEUgRSBFIEUgREhUbETMVRRFIE
UgRSBFIEUgRSBFIEUgRSBESFRsRMxVFEUgRSBFIEUgRSBFIEUgRSBFIA==
The payload can be split on the comma character into 2 parts:
Code: Select all
003508 RF address of the device
0gA1...IA== Base 64 encoded configuration data
Code: Select all
00: D2 00 35 08 01 01 14 FF 49 45 51 30 31 30 39 31 |Ò.5....ÿIEQ01091
10: 32 35 28 28 3D 09 07 28 03 30 0C FF 00 44 48 55 |25((=..(.0.ÿ.DHU
20: 08 45 20 45 20 45 20 45 20 45 20 45 20 45 20 45 |.E E E E E E E E
30: 20 45 20 45 20 45 20 44 48 55 08 45 20 45 20 45 | E E E DHU.E E E
40: 20 45 20 45 20 45 20 45 20 45 20 45 20 45 20 45 | E E E E E E E E
50: 20 44 48 54 6C 44 CC 55 14 45 20 45 20 45 20 45 | DHTlDÌU.E E E E
60: 20 45 20 45 20 45 20 45 20 45 20 44 48 54 6C 44 | E E E E E DHTlD
70: CC 55 14 45 20 45 20 45 20 45 20 45 20 45 20 45 |ÌU.E E E E E E E
80: 20 45 20 45 20 44 48 52 6C 44 CC 55 14 45 20 45 | E E DHRlDÌU.E E
90: 20 45 20 45 20 45 20 45 20 45 20 45 20 45 20 44 | E E E E E E E D
A0: 48 54 6C 44 CC 55 14 45 20 45 20 45 20 45 20 45 |HTlDÌU.E E E E E
B0: 20 45 20 45 20 45 20 45 20 44 48 54 6C 44 CC 55 | E E E E DHTlDÌU
C0: 14 45 20 45 20 45 20 45 20 45 20 45 20 45 20 45 |.E E E E E E E E
D0: 20 45 20 | E
Code: Select all
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)
L response ("Device List")
This reponse contains real-time information about the devices.
Example:
L:CwA1CAASGiAshYsu
Decoded in hex view:
Code: Select all
00: 0B 00 35 08 00 12 1A 20 2C 85 8B 2E |..5.... ,…‹.
Code: Select all
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)
This command contains the information for setting the valvues to a certain temperature and ending date and time.
Example: set valvue to 20 degrees, endtime 11-9-2011 15:30
s:AARAAAAAAP4wAaiLix8=\r\n
Decoded to hex:
Code: Select all
00 04 40 00 00 00 00 FE 30 01 A8 8B 8B 1F
Code: Select all
Start Length Value Description
==================================================================
00 1 00 ?, seems to be always this value
01 1 04 ?, seems to be always this value
02 1 40 ?, seems to be always this value
03 1 00 ?, seems to be always this value
04 1 00 ?, seems to be always this value
05 1 00 ?, seems to be always this value
06 3 00FE30 RF address valvue
09 1 01 ?, seems to roomnumber or nr (first valvue is 01, second is 02)
10 1 A8 Temperature setpoint, Temp uses 6 bits LSB6 (bit 2 tm 7),
20 deg C = bits 101000 = dec 40/2 = 20 deg C,
you need 8 bits to send so add the 2 bits below (sample 10101000 = hex A8)
bit 0,1 = 00 = Auto weekprog (no temp is needed, just make the whole byte 00
01 = Permanent
10 = Temporarily
11 2 8B8B Date until (11-09-2011) (see Encoding/Decoding date/time)
13 1 1F Time until (15:30) (see Encoding/Decoding date/time)
if you send 000000 for date and time (byte 11 tm 13) then there is no end time.
Code: Select all
00 04 40 00 00 00 00 FE 30 01 00 (Weekprog, with 00 in Temp byte 10, no date and time bytes needed)
00 04 40 00 00 00 00 96 3D 02 00 (Weekprog, same like above but for second valvue)
00 04 40 00 00 00 00 FE 30 01 6C (Set permanent to 22 degrees)
00 04 40 00 00 00 00 FE 30 01 AE 8C 8B (Set to 23 degrees temporary with endtime)
The script below can be used to decode Base64 encoded data and to encode binary (or anything else) data to Base64.
Code: Select all
Sub Main(parm as object)
'b64 is a string containing base-64 encoded data
Dim b64 As String = "CwA6FwASGUAqAAAACwA13QASGQoqAAAA"
'convert base64 string to hex string
Dim hx As String = Base64ToHex(b64)
'convert hex string to base64 string
Dim b64b As String = HexToBase64(hx)
End Sub
Private Function Base64ToHex(base64string As String) As String
Dim ret As String
Dim b64bytes() As Byte = System.Convert.FromBase64String(base64string)
For Each b As Byte In b64bytes
ret &= Hex(b).PadLeft(2, "0"c)
Next
Return ret
End Function
Private Function HexToBase64(ByVal HexText As String) As String
Dim HexTextBytes As Integer = HexText.Length \ 2 -1
Dim result(HexTextBytes) As Byte
Dim i As Integer
For i = 0 To HexTextBytes
result(i) = Convert.ToByte(HexText.Substring(i * 2, 2), 16)
Next
Return Convert.ToBase64String(result)
End Function
Coding/Decoding Date & Time
The way in which the date is stored is not very obvious; for example, the bits for encoding/decoding the month are scattered accross 2 bytes.
To store the complete date, 2 bytes are used. To decode the day-,month- and year value use the following
(value is the 2 bytes for the date)
Month: ((value & E000h) >> 12)+((value & 80h) >> 7)
Day : (value & 1F00h) >> 8
Year : (value & 0Fh)+2000d
& means "and"
>> means shift right aka shr
Date example:
Code: Select all
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
04 4 * 0.5 hours = 02:00
The weekly program
A big part of the configuration data (the C response) is used to define the weekly program.
This weekly program can be found from position 1Dh. From there you can find 26 bytes for each day of the week, starting with Saturday. Each pair of bytes (word) can be decoded as follows, taking 55 14 as an example:
Code: Select all
5514h = 0101010100010100b
101010 101010b = 42 decimal; 42/2 = 21 degrees Celsius
100010100 100010100b = 276 decimal; 276*5 minutes = 1380 minutes = 23:00
Code: Select all
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:";