Hi Roemer,
Good to see that someone else is also interested in getting the Luxtronik / Alpha Innotec heatpump data into Home Assistant over the network. Since I’m generally more interested in the general performance of the heatpump, I’ve whipped up a component that only reads the status, indoor, outdoor and boiler temperature values. In December I’ve written my first component prototype and a week ago I’ve made some small changes to the status reading, which deals with the Luxtronic not responding to network requests (which it occasionally does when it is too busy doing other stuff), which I wanted to test before I published the component. Over the last days this version has been running smoothly and it really gives a good insight in the operation of the heatpump and the triggering values.
Here is the code that I’m using, currently in a custom component:
import logging
from collections import namedtuple
from datetime import timedelta
import voluptuous as vol
import socket
import struct
import datetime
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import (
CONF_NAME, CONF_HOST, CONF_PORT,
STATE_UNKNOWN, STATE_ON )
from homeassistant.helpers.entity import Entity
import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__)
ATTR_TEMPERATURE_OUTDOOR = 'temperature_outdoor'
ATTR_TEMPERATURE_INDOOR = 'temperature_indoor'
ATTR_TEMPERATURE_BOILER = 'temperature_boiler'
ATTR_STATUS = 'status'
DEFAULT_NAME = 'Luxtronik'
SCAN_INTERVAL = timedelta(minutes=1)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_PORT): cv.port,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the RESTful sensor."""
name = config.get(CONF_NAME)
host = config.get(CONF_HOST)
port = config.get(CONF_PORT)
add_devices([Luxtronik(hass, name, host, port)])
class Luxtronik(Entity):
"""Representation of a Sensor."""
def __init__(self, hass, name, host, port):
"""Initialize the sensor."""
self._hass = hass
self._name = name
self._host = host
self._port = port
self._state = STATE_UNKNOWN
self.output = None
self.status = namedtuple(
'status', [ ATTR_TEMPERATURE_OUTDOOR, ATTR_TEMPERATURE_INDOOR,
ATTR_TEMPERATURE_BOILER, ATTR_STATUS ])
self.update()
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def state(self):
"""Return the state of the sensor."""
return self._state
@property
def state_attributes(self):
"""Return the state attributes of the monitored installation."""
if self.output is not None:
return {
ATTR_TEMPERATURE_OUTDOOR: self.output.temperature_outdoor,
ATTR_TEMPERATURE_INDOOR: self.output.temperature_indoor,
ATTR_TEMPERATURE_BOILER: self.output.temperature_boiler,
ATTR_STATUS: self.output.status,
}
def update(self):
"""Fetch new state data for the sensor.
This is the only method that should fetch new data for Home Assistant.
"""
try:
s = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
s.settimeout( 1 )
s.connect( (self._host, self._port) )
s.send( struct.pack( '!i', 3004 ) )
s.send( struct.pack( '!i', 0 ) )
if struct.unpack( '!i', s.recv(4) )[0] != 3004:
# self.output = None
_LOGGER.error(
"Unable to fetch data from Luxtronik, no 3004" )
# self._state = STATE_UNKNOWN
else:
stat = struct.unpack( '!i', s.recv(4) )[0]
len = struct.unpack( '!i', s.recv(4) )[0]
array_calculated = []
for i in range(len):array_calculated.append(struct.unpack( '!i', s.recv(4) )[0])
s.close()
if array_calculated[80] == 0:
status = 'heating'
elif array_calculated[80] == 1:
status = 'hot water'
elif array_calculated[80] == 2:
status = 'swiming pool / photovoltaic'
elif array_calculated[80] == 3:
status = 'power supply'
elif array_calculated[80] == 4:
status = 'defrost'
elif array_calculated[80] == 5:
status = 'no request'
elif array_calculated[80] == 6:
status = 'heating ext. power source'
elif array_calculated[80] == 7:
status = 'cooling'
else:
status = 'not known'
self.output = self.status._make([
float(array_calculated[15])/10,
float(array_calculated[227])/10,
float(array_calculated[17])/10,
status,
])
self._state = STATE_ON
except:
# self.output = None
_LOGGER.error(
"Unable to fetch data from Luxtronik" )
# self._state = STATE_UNKNOWN
As you can see, it should be fairly easy to get other sensor values into HASS if you want to. For me the current set of values are more than enough.
The configuration is quite self explanatory:
sensor:
- platform: luxtronik
name: Luxtronik
host: 192.168.1.X
port: 8889
- platform: template
sensors:
luxtronik_temperature_indoor:
friendly_name: 'Indoor'
value_template: '{{ states.sensor.luxtronik.attributes.temperature_indoor }}'
unit_of_measurement: '°C'
icon_template: 'mdi:home'
luxtronik_temperature_outdoor:
friendly_name: 'Outdoor'
value_template: '{{ states.sensor.luxtronik.attributes.temperature_outdoor }}'
unit_of_measurement: '°C'
icon_template: 'mdi:tree'
luxtronik_temperature_boiler:
friendly_name: 'Boiler'
value_template: '{{ states.sensor.luxtronik.attributes.temperature_boiler }}'
unit_of_measurement: '°C'
icon_template: 'mdi:water-pump'
luxtronik_status:
friendly_name: 'Status'
value_template: '{{ states.sensor.luxtronik.attributes.status }}'
icon_template: 'mdi:gauge'
I also use a group to bundle all the information neatly in the UI:
luxtronik:
name: Luxtronik
icon: 'mdi:desktop-tower'
entities:
- sensor.luxtronik_status
- sensor.luxtronik_temperature_indoor
- sensor.luxtronik_temperature_outdoor
- sensor.luxtronik_temperature_boiler
When I have a bit of time I’m very much willing to turn this into a component which can be included into Home Assistant by default, but before that I’m happy to receive feedback into the values that people would want to read out.
Hope this helps to get you started.