MAX! HOME AUTOMATION
version 2.4
by Dmitry A. Kazakov

(mailbox@dmitry-kazakov.de)
[Home]

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


MAX! home automation is a GTK+ application to manage ELV/eQ-3 MAX! cubes. A cube is a gateway to a network of radiator thermostats, shutter contacts etc.

      ARM Intel
Download MAX! home automation Platform:   v7 64- 32bit
Fedora packages fedora      precompiled and packaged using RPM     [Download page] [Download page] [Download page]
CentOS packages CentOS   precompiled and packaged using RPM       [Download page] [Download page]
Debian packages Debian   precompiled and packaged for dpkg   [Download page] [Download page] [Download page]
Ubuntu packages Ubuntu   precompiled and packaged for dpkg   [Download page] [Download page] [Download page]
Windows installer     max_home_automation_setup_2_4.exe   [Download]
Source distribution (any platform)   max_home_automation_2_4.tgz (tar + gzip, Windows users may use WinZip)   [Download]

See also the changes log.

The application is based on the ELV/eQ-3 cube client protocol stack implementation. The stack is distributed under the GM GPL license and is free to use independently on this application.


[TOC][Next]

1. Use

When the application starts is scans the local area network (LAN) for connected MAX! cubes. Once a cube is found the radio network topology is shown on the overview pane.

1.1. Overview pane

 

Depending on the LAN configuration it could be impossible to find the cube. In that case the address of a MAX! cube can be entered manually after pressing the button . Note the bar near the cube address. It indicates the amount of 800 MHz radio traffic used by the cube. The traffic is limited. When the limit is exhausted the cube stops transmitting commands controlling the thermostats. The limit is reset each hour.

When a thermostat is selected its operating mode can be changed in the combo box:

Additional parameters like vacation end time and set temperature appear. The mode is changed by pressing the mode set button . Note that the cube performs mode change asynchronously. It could take a considerable time before the thermostat reacts to the change. While doing that the cube continues to report the previous operation mode. When the thermostat ultimately changes the mode and the cube becomes aware of that, the actual mode gets reflected on the overview panel.

1.2. Thermostat settings pane

The thermostat settings and time schedule is shown when the configure device button is clicked:

For each week day you can define thermostat temperatures, maximum up to 13 points per day. Each point defines the temperature and the time until the thermostat must keep that temperature. The time resolution is 5 minutes. The temperature resolution is 5 Centigrade.

The day schedule points are automatically sorted according to the time column. If you have to insert a new point enter it into any unused row. Multiple points can be copied. The whole week schedule can be taken from another thermostat when the copy from button is pressed:

A week thermostat schedule can be written into and read from a file. The file format is portable across supported operating systems.

1.3. Trace pane

The trace pane indicated the exchange with the cube and other network parties (e.g. SMTP server):

Tracing can be additionally directed to a file. Buttons clear/stop/start control only tracing into the pane. Tracing into the file, when enabled, continues uninterrupted.

1.4. Graphs pane

The graphs page contains one pane per room. A room's pane has stacked oscilloscopes one per thermostat indicating the measured room temperature (red), the valve position (yellow) if the thermostat is a radiator thermostat. The gray curve is the set temperature plus thermostat offset, the value used by control the heater:

1.5. Scanning temperatures measured by radiator thermostat

The application deploys a technique forcing radiator thermostats to report measured temperatures. A radiator thermostat installed in the room managed by a wall-mounted thermostat reports the temperature measured by the wall-mounted thermostat instead of its own temperature. When installed in an unmanaged room with no wall-mounted thermostats a radiator thermostat reports its own measured temperature but only when either its valve position is changed or its operating mode is. For such "unmanaged" thermostats the application temporarily alters the thermostat mode from automatic to manual or conversely, when there no recent measured temperature known. As soon as the thermostat refreshes the measured temperature it is switched back to the original mode.

The following parameters on the settings page control this scanning behavior:

1.6. Cube discovery

The application's setting pane controls the method cubes are discovered and connected.

1.7. Saving and restoring thermostat configurations

When a cube is selected configurations of all its radiator thermostats can be stored into and restored from a file. The items saved are:

Upon restoring configuration the following pane is shown:

Upon reading the file application tries to match addresses or names of the saved thermostats with the addresses and names of existing thermostats. The match is shown in the column get from. The column contains combo-boxes where another source thermostat or no thermostat can be selected. When no thermostat address is selected in the combo box, the existing thermostat's configuration is not touched. Additionally the items to restore can be selected in the check boxes below.

Note that restoring configurations of many thermostats requires much of radio traffic. When the traffic limit is exhausted the cube stops accepting further commands. The bar at the cube address will show 100% and an exclamation sign will appear. After that an hour is required to wait until restoring can be continued. Successfully restored thermostat configurations are skipped. The retry button starts failed configuration over again.


[Back][TOC][Next]

2. HTTP automation

The application has an integrated HTTP server than can be used to control the connected cubes. The server is disabled by default. It can be enabled through the settings pane. The HTTP server port can be set to a value different from the standard 80, when it is already used. The server supports the HTTP GET requests described below:

2.1. Querying a device status

http://<max-home-automation>/get-status?cube=<address>[&device=<address>]

Here <max-home-automation> is the name or IP-address of the server. <address> is the RF address (hexadecimal) of the cube and the device correspondingly. For example, assuming accessing the server at the localhost:

http://127.0.0.1/get-status?cube=0BB8F0&device=10A40C

The server response describes the current device status in textual format. Its components depend on the device type. When device address is absent the response lists statuses of all devices controlled by the cube. Individual parts of the status can be queried by the following queries

http://<max-home-automation>/get-status-json?cube=<address>[&device=<address>]

This query is analogous to get-status except that it reports the status of a device or of all available devices in the JSON parser format.

http://<max-home-automation>/get-status-csv?cube=<address>[&device=<address>]

This query is analogous to get-status except that it reports the status of a device or of all available devices in the CSV format. The output contains one line for each device. The line has the following fields separated by semicolon, all fields except the last one are numeric:

No. Value Values
1 The device type
Device Value
cube 0
radiator thermostat 1
radiator thermostat plus 2
wall thermostat 3
shutter contact 4
eco button 5
unknown 6
2 The device RF address, hexadecimal 000000..FFFFFF
3 The device error 0..1
4 Device initialized 0..1
5 Battery low 0..1
6 Error 0..1
7 Panel locked 0..1
8 Gateway known 0..1
9 Day saving time 0..1
10 Mode
Mode Value
automatic 0
manual 1
boost 2
vacation 3
11 Set temperature  
12 New temperature  
13 Valve position 0..100
14 Actual temperature 0 if not known
15 Open (shutter contact) 0..1
16 Offset (thermostat)  
17 Serial number KEQ0828854

http://<max-home-automation>/get-battery?cube=<address>&device=<address>

This query is responded with the current battery level of a device. The returned value is high or low.

http://<max-home-automation>/get-link?cube=<address>&device=<address>

This query is responded with the radio link of a device. The returned value is error or ok.

http://<max-home-automation>/get-mode?cube=<address>&device=<address>

This query is responded with the current mode of a thermostat. The returned values are automatic, manual, boots, vacation.

http://<max-home-automation>/get-rooms-list?cube=<address>

This query is responded with the list of rooms per line. For each room the corresponding line of the response contains the list of space separated RF-addresses of the devices in  the room, followed by the room ID and name. The room ID is introduced by dash (#), the name is by minus (-). For example:

0B76D4 0CB6E2 #1 - Small room on the left
0B7E19 0C9809 0CB7FF #2 - Bedroom
0B76DA 0C9E44 0CB003 17EE29 #3 - Recreation room
0C8EA2 0CA489 0CB6D6 10A40C #4 - Big room on the right
050F6D 12F4E0 #5 - Bathroom

http://<max-home-automation>/get-rooms-json-list?cube=<address>

This query is responded with the list of rooms in JSON format. For each room the response contains the room name, the room ID and the list of RF-addresses of the devices in  the room.

http://<max-home-automation>/get-temperature?cube=<address>&device=<address>

This query is responded with the current temperature measured by a wall-mounted thermostat in Centigrade.

http://<max-home-automation>/get-set-temperature?cube=<address>&device=<address>

This query is responded with the current set temperature of a thermostat in Centigrade.

http://<max-home-automation>/get-summer-time?cube=<address>&device=<address>

This query is responded with the device summer time settings. The returned value is yes or no.

http://<max-home-automation>/get-valve?cube=<address>&device=<address>

This query is responded with the current valve position of a radiator thermostat 0-100%. The value 100% corresponds to the fully opened valve.

http://<max-home-automation>/get-valve-average?cube=<address>

This query is responded with the average valve position of radiator thermostats handled by the cube.

http://<max-home-automation>/get-valve-min?cube=<address>

This query is responded with the minimum valve position of all radiator thermostats handled by the cube.

http://<max-home-automation>/get-valve-max?cube=<address>

This query is responded with the maximum valve position of all radiator thermostats handled by the cube.

2.2. Setting thermostats into automatic mode

http://<max-home-automation>/set-automatic?cube=<address>[&device=<address>]

or

http://<max-home-automation>/set-automatic?cube=<address>[&device=<address>]&{temperature[+|-]=<value>|airing|comfort|eco}

For example:

http://127.0.0.1/set-automatic?cube=0BB8F0&device=10A40C

The temperature is specified by the parameter <value>. It can be a relative or absolute value. For example an absolute temperature specification:

http://127.0.0.1/set-automatic?cube=0BB8F0&device=10A40C&temperature=18.5

Here the thermostat 10A40C is set to keep 18.5 Centigrade until the next time interval, when it returns to the schedule. The following is a example of setting the temperature relative to the current one:

http://127.0.0.1/set-automatic?cube=0BB8F0&device=10A40C&temperature+=0.5

In this example  the temperature is incremented by 0.5 Centigrade.

Additionally one of the following keywords can be used for the temperature:

The following request sets airing temperature:

http://127.0.0.1/set-automatic?cube=0BB8F0&device=10A40C&airing

The field device=<address> can be omitted. In this case the command applies to all thermostats, e.g.

http://127.0.0.1/set-automatic?cube=0BB8F0&eco

Here all thermostats set to the corresponding eco temperature (until the next time slice in the schedule).

2.3. Setting thermostats into boost mode

http://<max-home-automation>/set-boost?cube=<address>[&device=<address>]

For example:

http://127.0.0.1/set-boost?cube=0BB8F0&device=10A40C

2.4. Setting thermostats into manual mode

http://<max-home-automation>/set-manual?cube=<address>[&device=<address>]&{temperature[+|-]=<value>|airing|comfort|eco}

The temperature is specified by the parameter <value>. It can be a relative or absolute value. For example an absolute temperature specification:

http://127.0.0.1/set-manual?cube=0BB8F0&device=10A40C&temperature=18.5

Here the thermostat 10A40C is set to keep 18.5 Centigrade. The following is a example of setting the temperature relative to the current one:

http://127.0.0.1/set-manual?cube=0BB8F0&device=10A40C&temperature+=0.5

In this example  the temperature is incremented by 0.5 Centigrade.

2.5. Setting thermostats into vacation mode

http://<max-home-automation>/set-vacation?cube=<address>[&device=<address>]&{temperature[+|-]=<value>|airing|comfort|eco}&{weeks|days|hours|minutes}=<count>

For the vacation mode again the temperature can be specified relative or absolute. The vacation end time is given as a number <count> of weeks, days, hours or minutes. For example:

http://127.0.0.1/set-vacation?cube=0BB8F0&device=10A40C&temperature=16&days=2

Here the thermostat 10A40C is set to keep 16 Centigrade for two days. After that it will switch back into its previous mode.


[Back][TOC][Next]

3. MQTT automation

The integrated MQTT server allows access and control of the cubes through the Message Queueing Telemetry Transport (MQTT). MQTT is an ISO standard (ISO/IEC PRF 20922) messaging protocol. By default the MQTT server is disabled. It is enabled through the settings pane.

3.1. Published topics

The server publishes data received from the cube as retained topics:

Topic Contents
<cube-address>/shutter contact/<device-address>/battery low, high
<cube-address>/shutter contact/<device-address>/status open, close
<cube-address>/radiator thermostat/<device-address>/battery low, high
<cube-address>/radiator thermostat/<device-address>/mode automatic, manual, boost, vacation
<cube-address>/radiator thermostat/<device-address>/set temperature 19.0
<cube-address>/radiator thermostat/<device-address>/temperature 19.5
<cube-address>/radiator thermostat/<device-address>/valve 30
<cube-address>/thermostat valves/average 50
<cube-address>/thermostat valves/max 70
<cube-address>/thermostat valves/min 30
<cube-address>/wall thermostat/<device-address>/battery low, high
<cube-address>/wall thermostat/<device-address>/mode automatic, manual, boost, vacation
<cube-address>/wall thermostat/<device-address>/set temperature 19.0
<cube-address>/wall thermostat/<device-address>/temperature 19.5

Here <cube-address> is the RF address (hexadecimal) of the cube. <device-address> is the RF address of the device. All topics are retained, that means a client may subscribe to them at any time and get the latest values of. The topic .../thermostat valves/average contains the average valve position of all cube's radiator thermostats. The topics .../thermostat valves/min and .../thermostat valves/max are correspondingly the minimum and maximum valve positions among cube's radiator thermostats.

3.2. Controlling thermostats

A thermostat can be controlled by publishing special topics on the server. The server does not propagate or retain these topics.

Topic Contents
<cube-address>/set[/<device-address>]/automatic [[+|-]<temperature>]|airing|eco|comfort
<cube-address>/set[/<device-address>]/boost -
<cube-address>/set[/<device-address>]/manual [+|-]<temperature>|airing|eco|comfort
<cube-address>/set[/<device-address>]/vacation {[+|-]<temperature>|airing|eco|comfort} <count>{weeks|days|hours|minutes}

Here <cube-address> is the RF address (hexadecimal) of the cube. <device-address> is the RF address of the device, which must be a thermostat. When <device-address> is absent the command applies to all radiator thermostats. <temperature> is the temperature to set. When a sign is used the temperature is relative to the actual set value. <count> is the number of weeks, days, hours, minutes as specified. Additionally one of the following keywords can be used for the temperature:

3.3. Externally published topics

By default the MAX! home automation MQTT broker rejects client's attempts to publish any topics beyond ones to control the thermostats. This behavior can be changed on the settings pane by allowing MQTT publishing. Further the list of allowed topics can be specified. When the list is empty any topic can be published. Otherwise it contains a comma-separated list of MQTT topic patterns. A topic is published if it matches at least one item from the list.

MQTT publishing can be used together with Python scripting to connect external sensors connected to a MQTT client. The client can publish sensor readings as retained MQTT topics on the MAX! home automation MQTT broker. The Python script can read the published messages (see get_mqtt_message) and use the data for control.


[Back][TOC][Next]

4. Logging into a database

The device data can be stored into a database, for example in order to accumulate long-term statistics. New data are logged only if changed. Repeating values are ignored.

4.1. Database configuration

The settings pane has database section allowing database configuration:

ODBC and SQLite are supported interfaces.

4.1.1 ODBC

ODBC stands for Open Database Connectivity. The database configuration consists of:

The database may be located on a different computer and run under a different OS.

ODBC drivers are provided by the database vendors. Most commonly used databases support ODBC, e.g. Microsoft SQL Server, Microsoft Access, Oracle, Sybase, MySQL, PostgreSQL to name few.

4.1.2 SQLite

SQLite is a single-file database. All database is stored in the file which is usually located on the local file system. The database file name is all that has to be configured. When the file does not exist, it is automatically created.

4.2. The database structure

The data are stored into the table named datalog. The table has the following columns:

Name Type Contents
time_stamp String
 or
Timestamp
  • For SQLite the timestamp is a text in the format: 2017-02-18 14:00:30.12
  • For ODBC a database native timestamp type is used
address Integer The RF-address of the device
device_type Integer
Device Value
cube 0
radiator thermostat 1
radiator thermostat plus 2
wall thermostat 3
shutter contact 4
eco button 5
unknown 6
set_temperature Real The temperature kept by the thermostat
new_temperature Real The new temperature for the thermostat. It differs from the above if the thermostat is not yet aware of the change
is_temperature Real The actual room temperature
offset Real The temperature offset to add to the set-temperature. The result is used as the target by the thermostat
valve_position Integer 0..100. The value 100 corresponds to a fully open valve
contact_open Integer 0..1. The value 1 means open contact. This column is filled by window shutter contacts
error Integer 0..1. The value 1 means error
duty Integer 0..100. This column is filled by cube
slots Integer The number of free slots. This column is filled by cube
battery_low Integer 0..1
panel_locked Integer 0..1
current_mode  
Mode Value
automatic 0
manual 1
boost 2
vacation 3

The table is created automatically if does not exist. For ODBC data types of the columns are selected according to the capacities of the database management system (DBMS).


[Back][TOC][Next]

5. Scripting

5.1. Python scripting

Simple control tasks can be performed by providing a Python script to be called periodically. The script can access the application through the module elv_max_home. The module is loaded as shown in the following example:

# Minimal controller script
import elv_max_cube
def controller (*args):
   elv_max_cube.trace ("Hello there!")

The settings pane has Python script settings:

Here the fields are:

5.2. Python module elv_max_home

The following method are provided by the module elv_max_home:

get_battery
get_cubes_list
get_devices_list
get_link
get_mode
get_mqtt_message
get_parameters
get_status
get_temperature
get_set_temperature
get_summee_time
get_valve
get_valve_statistic
set_mode
publish_mqtt_message
trace

5.2.1. get_battery

elv_max_cube.get_battery (cube, device)

This method returns the battery state by the RF address of the cube and the RF address of the device. The result is 'high' or 'low'. TypeError is when no device was found or it has no battery. For example the following code lists battery state of a device:

elv_max_cube.trace ("Battery state: " + elv_max_cube.get_battery (0x0BB8F0, 0x0B76DA))

5.2.2. get_cubes_list

elv_max_cube.get_cubes_list

This method returns the list of RF addresses, one address for each detected cube. For example the following code lists all cubes:

cubes_list = elv_max_cube.get_cubes_list ()
elv_max_cube.trace ("MAX! cubes detected: " + ", ".join ('{:06X}'.format (cube) for cube in cubes_list))

5.2.3. get_devices_list

elv_max_cube.get_devices_list (cube, device_types)

This method returns the list of RF addresses of the devices managed by the cube and filtered by the type. The parameter cube is the RF address of the cube. When 0 the devices are taken from any cube. device_types is the list of device types to accept. It can contain any of: 'cube', 'radiator thermostat', 'radiator thermostat plus', 'wall thermostat', 'shutter contact', 'eco button'. The following example lists all radiator thermostats managed by the the cube with the address 0BB8F0:

thermostats_list = elv_max_cube.get_devices_list (0x0BB8F0, ['radiator thermostat', 'radiator thermostat plus'])
elv_max_cube.trace ("Thermostats: " + ", ".join ('{:06X}'.format (thermostat) for thermostat in thermostats_list))

5.2.4. get_link

elv_max_cube.get_link (cube, device)

This method returns the link state by the RF address of the cube and the RF address of the device. The result is 'error' or 'ok'. TypeError is when no device was found or it has no link state. For example the following code shows link state of a device:

elv_max_cube.trace ("Link state: " + elv_max_cube.get_link (0x0BB8F0, 0x0B76DA))

5.2.5. get_mode

elv_max_cube.get_mode (cube, device)

This method returns the link state by the RF address of the cube and the RF address of the device. The result is 'automatic', 'manual', 'boost', 'vacation'. TypeError is raised when no device was found or it has no mode. For example the following code lists all cubes:

elv_max_cube.trace ("Mode: " + elv_max_cube.get_mode (0x0BB8F0, 0x0B76DA))

5.2.6. get_mqtt_message

elv_max_cube.get_mqtt_message (topic)

This method returns retained message from the MAX! home automation broker. The parameter topic specifies the message topic. When the topic is invalid or when no message exists TypeError is raised. The following example illustrates getting topic Greeting:

elv_max_cube.trace ("Message: " + elv_max_cube.get_mqtt_message ("Greeting")

5.2.7. get_parameters

elv_max_cube.get_parameters (cube, device)

This method returns a dictionary describing parameters of  device handled by cube. The dictionary contains the following key some of which can be absent depending on the device type:

Key Type Contents
address long The RF-address of the device
airing temperature float The thermostat room airing temperature (Centigrade)
airing mode delay string The duration in the format HH:MM
boost duration string The duration of the thermostat boost mode in the format HH:MM
boost valve position float The valve position in the boost mode in the range 0..1. 1 corresponds to a fully open valve
comfort temperature float The thermostat comfort temperature (Centigrade)
decalcification time dictionary The week day and time to perform the procedure:
Key Type Contents
day string The week day, e.g. 'Monday'
time string The time in the format HH:MM
eco temperature float The thermostat eco temperature, when in the 'eco' mode (Centigrade)
maximum valve position float The thermostat maximum valve position in the range 0..1. 1 corresponds to a fully open valve
maximum temperature float The thermostat maximal temperature (Centigrade)
minimum temperature float The thermostat minimum temperature (Centigrade)
room string The device's room name
room id long The ID number of the device's room
name string The device name
schedule dictionary The thermostat schedule in the automatic mode:
Key Type Contents
Monday list The thermostat scheduling points on Monday. The points in the list are ordered by the time. Each point is the dictionary:
Key Type Contents
until string The time in the format HH:MM until the specified temperature must be held
temperature float The set temperature in Centigrade
Tuesday list The thermostat scheduling points on Tuesday
Wednesday list The thermostat scheduling points on Wednesday
Thursday list The thermostat scheduling points on Thursday
Friday list The thermostat scheduling points on Friday
Saturday list The thermostat scheduling points on Saturday
Sunday list The thermostat scheduling points on Sunday
serial no string The device serial number
temperature offset float The thermostat temperature offset (Centigrade)
type string
Device
cube
radiator thermostat
radiator thermostat plus
wall thermostat
shutter contact
eco button
unknown
valve float The value 1.0 corresponds to a fully open valve

TypeError is when no device was found. The following example illustrates tracing state of the thermostat 0B76DA  managed by the the cube with the address 0BB8F0:

elv_max_cube.trace ("Parameters " + str (elv_max_cube.get_parameters (0x0BB8F0, 0x0B76DA)))

Possible output could be: Status {'type': 'radiator thermostat', 'address': 751322, 'mode': 'manual', 'error': True, 'initialized': True, 'valve': 0.1298828125, 'set temperature': 17.0, 'new temperature': 17.0, 'panel locked': False, 'battery low': False, 'link error': False, 'summer time': True}

5.2.8. get_status

elv_max_cube.get_status (cube, device)

This method returns a dictionary describing status of  device handled by cube. The dictionary contains the following key some of which can be absent depending on the device type:

Key Type Contents
address long The RF-address of the device
battery low True/False True if battery is low
error True/False True if error
initialized True/False True if initialized
link error True/False True if link error
mode string
Mode
automatic
manual
boost
vacation
new temperature float The new temperature for the thermostat. It differs from the above if the thermostat is not yet aware of the change
open True/False True if shutter contact is open
panel locked True/False True if locked
set temperature float The temperature kept by the thermostat
summer time True/False True if summer time
temperature float The actual room temperature, if known
type string
Device
cube
radiator thermostat
radiator thermostat plus
wall thermostat
shutter contact
eco button
unknown
valve float The value 1.0 corresponds to a fully open valve

TypeError is when no device was found. The following example illustrates tracing state of the thermostat 0B76DA  managed by the the cube with the address 0BB8F0:

elv_max_cube.trace ("Status " + str (elv_max_cube.get_status (0x0BB8F0, 0x0B76DA)))

Possible output could be: Status {'type': 'radiator thermostat', 'address': 751322, 'mode': 'manual', 'error': True, 'initialized': True, 'valve': 0.1298828125, 'set temperature': 17.0, 'new temperature': 17.0, 'panel locked': False, 'battery low': False, 'link error': False, 'summer time': True}

5.2.9. get_temperature

elv_max_cube.get_temperature (cube, device)

This method returns the current measured temperature by the RF address of the cube and the RF address of the device. The result is the measured temperature in Centigrade. TypeError is when no device was found, it has no temperature or when the temperature is yet unknown. For example the following code lists the measured temperature:

elv_max_cube.trace ("Temperature: " + str (elv_max_cube.get_temperature (0x0BB8F0, 0x0B76DA)))

5.2.10. get_set_temperature

elv_max_cube.get_set_temperature (cube, device)

This method returns the current set temperature by the RF address of the cube and the RF address of the device. The result is the temperature in Centigrade. The set temperature is used to control the radiator. TypeError is when no device was found or it has no temperature. For example the following code lists the set temperature:

elv_max_cube.trace ("Set temperature: " + str (elv_max_cube.get_set_temperature (0x0BB8F0, 0x0B76DA)))

5.2.11. get_summer_time

elv_max_cube.get_summer_time (cube, device)

This method returns the daytime saving mode of device specified by the RF address of the cube and the RF address of the device. True is he result when the summer time is active. TypeError is when no device was found or it has no time mode settings. For example the following code shows the active daytime saving mode:

elv_max_cube.trace ("Summer time: " + str (elv_max_cube.get_summer_time (0x0BB8F0, 0x0B76DA)))

5.2.12. get_valve

elv_max_cube.get_valve (cube, device)

This method returns the valve position of a thermostat specified by the RF address of the cube and the RF address of the device. The result is in the range 0..1. The value 1 corresponds to a fully open valve. TypeError is when no device was found or it is not a thermostat. For example the following code shows the valve position of a thermostat:

elv_max_cube.trace ("Valve: " + str (elv_max_cube.get_valve (0x0BB8F0, 0x0B76DA)))

5.2.13. get_valve_statistics

elv_max_cube.get_valve_statistics (cube)

This method returns the statistics of the current thermostat valve positions. The parameter cube is the RF address of the cube which thermostats are queried. The result is the dictionary:

Key Type Contents
average float The average valve position
maximum float The maximal valve position
minimum float The minimal valve position

The valve position is in the range 0..1. The value 1 corresponds to a fully open valve. When there is no thermostats corresponding, the returned fields are 0.

elv_max_cube.trace ("Average valve position: " + str (elv_max_cube.get_valve_statistics (0x0BB8F0) ['average']))

5.2.14. set_mode

elv_max_cube.set_mode (mode, cube, device, temperature, disposition, until)

This method sets one or several thermostats into the specified mode. The method takes keyed parameters with the names given in the following table:

Key Type Contents
mode string The thermostat mode to set:
Mode
automatic
manual
boost
vacation

This parameter is obligatory. If omitted TypeError is raised.

cube long The RF address of the cube of which thermostats must be set. This parameter must be always present. If omitted TypeError is raised.
device long The RF address of the thermostat to set. This parameter is optional. Then absent the mode is set into all thermostats of the cube
temperature float The temperature in Centigrade. This parameter is optional if the temperature is not required or specified by other means. When required but not specified TypeError is raised. The temperature is either absolute or relative to the current temperature as specified by the parameter disposition.
disposition string The parameter specifies how to treat the temperature parameter:
Disposition Meaning
absolute The value of the parameter temperature is used as-is for the mode to set. The temperature parameter must be present, otherwise TypeError is raised. This is the default when the temperature parameter is specified.
airing The airing mode temperature is used for the mode. The temperature parameter must be absent, otherwise TypeError is raised.
comfort The comfort temperature is used for the mode. The temperature parameter must be absent, otherwise TypeError is raised.
decrement The value of the parameter temperature is used to decrement the current temperature, the result is used for the mode. The temperature parameter must be present, otherwise TypeError is raised.
eco The eco temperature is used for the mode. The temperature parameter must be absent, otherwise TypeError is raised.
increment The value of the parameter temperature is used to increment the current temperature, the result is used for the mode. The temperature parameter must be present, otherwise TypeError is raised.
until float The duration of the set mode in seconds. This parameter must appear when the mode is vacation. It must be absent for any other mode, otherwise TypeError is raised.

The method is asynchronous. It only initiates setting the mode, which can take a considerable time or fail when the RF traffic is exhausted. The following example sets all thermostats to hold the eco temperature for one day:

elv_max_cube.set_mode (cube=0x0BB8F0, mode='vacation', disposition='eco', until=3600*24)

5.2.15. publish_mqtt_message

elv_max_cube.publish_mqtt_message (topic, message [, policy])

This method publishes topic with the message specified by message  the statistics of the current thermostat valve positions. The parameter policy is specifies how to handle the message:

Policy Description
Transient The message is not retained, only active subscriptions get it
Retained The message always replaces the retained one
Updated Ignored if same as the retained one, otherwise it replaces the old one. This is the default
Initial Ignored if already retained
Ignored The message is ignored

The following example illustrates publishing topic Greeting with the message Hi!

elv_max_cube.publish_mqtt_message ("Greeting", "Hi!")

5.2.16. trace

elv_max_cube.trace (message)

This method sends the argument message to the application's trace panel. There is no return value.

5.3. Maintaining state between calls of the script

Frequently it is necessary to keep certain data from one call to the script to another. When the script returns an object, which can be of any type, then this object is passed to the next call of the script as the single argument. During the first call the argument is set to None. The following example illustrates the concept by incrementing the count each time the script is called:

import elv_max_cube
def controller (*args):
   if args [0] is None:
      result = 0
   else:
      result = args [0] + 1
   elv_max_cube.trace ("Count =" + str (result))
   return result

When the argument args [0] is None, 0 is returned. Otherwise args [0] is incremented and then returned. Naturally, the result can be of any type. E.g. it can be a dictionary or list.

5.4. Controlling a boiler with an ESP8266 and a relay

This example illustrates using scripting in connection with MQTT messaging to control a boiler. The following picture illustrates the setup:

Here the components are:

MAX! home automation runs the following script:

import elv_max_cube
def controller (*args):
   if elv_max_cube.get_valve_statistics (0xBB8F0) ["average"] > 10:
      elv_max_cube.publish_mqtt_message ("relay", "on")
   else:
      elv_max_cube.publish_mqtt_message ("relay", "off")

The script takes the valves statistics of the radiator thermostats of the cube. Here BB8F0 is the cube's RF-address. It compares the averaged valve position. If that is bigger that 10% the topic relay is published as on. Otherwise it is published as off.

NodeMCU
 ESP8266 12E
  Wemos D1
mini relay
   
+ =

Now the Arduino program in C++ for ESP8266:

#include <OneWire.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char *  WiFi_SSID     = "<your WiFi network>";
const char *  WiFi_Password = "<your WiFi password>";
const char *  MQTT_Server   = "<your MAX! home automation IP address>";
const int     MQTT_Port     = 1883;
const int     Relay_Pin     = D1;

OneWire       One_Wire_Bus (4);         // onewire bus
WiFiClient    Networking;               // WiFi
PubSubClient  MQTT_Client (Networking); // MQTT

void Update_Subscription (char * topic, byte * payload, unsigned int length)
// This is called each time any subscribed topic arrive
   if (0 == strcmp (topic, "relay"))
   {  // This is the topic "relay" we are interested in
      if (2 <= length && 'o' == payload [0] && 'n' == payload [1])
      {  // Turn on
         Serial.println ("Relay on");
         digitalWrite (Relay_Pin, HIGH);
      }
      else
      {  // Turn off
         Serial.println ("Relay off");
         digitalWrite (Relay_Pin, LOW);
   }  }
}

void setup ()
// This is called once upon start
   Serial.begin (9600); // Initiate serial console with 9600 baud
   Serial.println ("Starting");

   pinMode (Relay_Pin, OUTPUT); // Configure relay
   setup_wifi ();               // Setup WIFI

   // Setup MQTT, but connect later from the main loop
   MQTT_Client.setServer (MQTT_Server, MQTT_Port);
   MQTT_Client.setCallback (&Update_Subscription);
}

void setup_wifi ()
{
   delay (10);
   // We start by connecting to a WiFi network
   Serial.println ();
   Serial.print ("Connecting to ");
   Serial.println (WiFi_SSID);

   WiFi.begin (WiFi_SSID, WiFi_Password);

   while (WiFi.status () != WL_CONNECTED)
   {
      delay (500);
      Serial.print (".");
   }
   Serial.println ("Connected, IP address: ");
   Serial.println (WiFi.localIP ());
}

void Reconnect_MQTT ()
{
   while (!MQTT_Client.connected ())
   {  // Loop until we're reconnected
      Serial.print ("Connecting to MQTT broker ...");
      if (MQTT_Client.connect ("ESP8266Client"))
      {
         Serial.println ("Connected");
         MQTT_Client.subscribe ("relay"); // Subscribe to the topic
      }
      else
      {
         Serial.print (" failed to connect, rc=");
         Serial.print (MQTT_Client.state ());
         Serial.println (" try again in 5 seconds");
         delay (5000); // Wait 5 seconds before retrying
   }  }
}

void loop ()
// Main loop
   if (!MQTT_Client.connected ())
   {  // Connect to the MQTT broker
      Reconnect_MQTT ();
   }
   MQTT_Client.loop (); // Pump network I/O
}

The program connects to the MAX! home automation MQTT broker and subscribes to the topic relay. When the payload is on the relay is set to closed, otherwise it is set to open. This is done by the command digitalWrite.


[Back][TOC][Next]

6. Running headless and other issues

6.1. Headless

In order to run the application headless under Linux use the following command (bash):

>xvfb-run -a max_home_automation

Here Xvfb is X virtual frame buffer, an X11 server that uses memory instead of a physical display. You might need to install it on your system if the package xvfb is not there.

6.2. Running remotely

Before running the application headless you might wish to change some settings or monitor how things work in general. You can run it remotely using the PC's X11 local server as the display for the remotely running program.

Linux. Under Linux you use SSH with X11 forwarding. The command line looks like follows:

>ssh -X -v <user>@<host> max_home_automation

Here <user> is the user you want to log in and <host> is the address or name of the machine where you want to run it, e.g. on your headless Raspberry PI. On the other side you must have the SSH daemon running.

Windows. Under Windows you need a X11 server and SSH client. There is a software that combines both: MobaXterm. Under MobaXterm you can configure an SSH session with X11 forwarding.

6.3. Permission denied

When you get error 13 permission denied upon HTTP start, that is because you lack permissions to bind the socket to the port 80. Usually only root can use ports with numbers below 1024 while the default HTTP port is 80. You may use another port or else run the software as root.


[Back][TOC][Next]

7. Building from sources

The program uses Simple Components for Ada, GtkAda contributions which are distributed with it. In order to compile it, GtkAda must be installed first. Then with GNAT compiler it can be built using the following command:

>gprbuild -XDevelopment=Release -p -P max_home_automation.gpr

issued in the directory containing the sources. Additionally depending on the target the following scenario variables are set:

Under Linux the file gtkada_contributions.gpr must be edited by replacing all appearances of "mwindows" with "-ldl".

You can also use the max_home_automation.gpr project with the GPS and compile it from there selecting scenarios described above.


[Back][TOC][Next]

8. Changes log

The following versions were tested with the compilers:

and the GtkAda versions:

Changes (9 January 2018) to the version 2.3:

Changes (6 January 2018) to the version 2.2:

Changes (26 December 2017) to the version 2.1:

Changes (21 December 2017) to the version 2.0:

Changes (18 December 2017) to the version 1.12:

Changes (26 November 2017) to the version 1.11:

Changes (5 September 2017) to the version 1.10:

Changes (26 July 2017) to the version 1.9:

The following versions were tested with the compilers:

and the GtkAda versions:

Changes (18 April 2017) to the version 1.8:

Changes (22 February 2017) to the version 1.7:

Changes (5 February 2017) to the version 1.6:

Changes (21 November 2016) to the version 1.5:

Changes (25 July 2016) to the version 1.4:

The following versions were tested with the compilers:

and the GtkAda versions:

Changes (31 May 2016) to the version 1.3:

The following versions were tested with the compilers:

and the GtkAda versions:

Changes (13 April 2016) to the version 1.2:

Changes (5 March 2016) to the version 1.1:

Changes (18 October 2015) to the version 1.0:

Version 1.0 released (24 August 2015).


[Back][TOC]

9. Table of Contents

1 Use
2 HTTP automation
   2.1. Querying a device status
   2.2. Setting thermostats into automatic mode
   2.3. Setting thermostats into boost mode
   2.4. Setting thermostats into manual mode
   2.5. Setting thermostats into vacation mode
3 MQTT automation
   3.1. Publishing topics
   3.2. Controlling thermostats
   3.3. Externally published topics
4 Logging into a database
   4.1. Database configuration
   4.2. The database structure
5 Scrpting
   5.1. Python scripting
   5.2. Python module elv_max_home
   5.3. Maintaining state between calls of the script
   5.4. Controlling a boiler with an ESP8266 and a relay
6 Runnung headless and other issues
   6.1. Headless
   6.2. Running remotely
   6.3. Permission denied
7 Building from sources
8 Changes log
9 Table of Contents