Ansteuerung OpenTherm

Hallo zusammen,

kennt hier jemand eine Idee wie man mit xcomfort eine OpenTherm Ansteuerung vornehmen kann.

Hintergrund ist ein Lüftungsgerät, welches man anstelle einen Stufenschalters über einen OT Anschluß stufenlos regulieren, bzw den Luftdurchsatz einstellen kann

Grüße
Michael

Deine Frage ist zwar schon etwas älter, aber vielleicht ist das hier ja trotzdem noch für jemanden von Interesse:

Controlling the central heating system

Mit dieser Hardware kann man sowohl die Kommunikation zwischen Raumthermostat und Therme monitoren als auch selbst Steuerbefehle senden. Das Ganze per serieller Schnittstelle. Es gibt auch eine Windows-Software vom Autor. Vielleicht lässt sich das so in IPS einbinden.

So, ich habe mir jetzt mal ein Kit von der weiterentwickelten Hardware bestellt. Werde dann berichten ob ich es in IPS eingebunden bekomme.

Hallo Titus,

Ich bin auch dran diese DIY Gateway für Opentherm zu bauen und damit meine Heizung zu steuern.
Hast du schon Erfolg?

Bisher noch nicht, warte noch auf das Paket. Hoffe es kommt die Tage.

Ich habe Opentherm mal nachgeroutet, kann es jemand gebrauchen ?

Wenn ja, Der muß die Schaltung kontrollieren :wink:

Gruß Helmut

So, nun endlich ist mein Gateway fertig und funktioniert so weit (einen Dank für die Hilfe an Roland Ketel!).

Die Kommunikation per USB funktioniert und auch das Raumthermostat spricht mit der Therme. Die Kommunikation kann ich mir in der Software „OpenTherm Monitor“ auch anschauen.

Leider ist mein Setup für den geplanten Zweck nicht geeignet. Das Raumthermostat Siemens QAA73 ist nicht in der Lage eine Nenntemperatur von extern anzunehmen. Eine Steuerung der Heizung per Gateway + IPS geht so leider nicht :mad:

Da werde ich wohl mal meinen Heizungsfachmann befragen müssen, ob ein anderes Thermostat problemlos eingesetzt werden kann.

Wer schauen will ob sein Setup funktioniert kann mal hier schauen: http://www.tclcode.com/opentherm/matrix.cgi

Noch ein kurzer Nachtrag :slight_smile:

Auch wenn eine Steuerung der Therme noch nicht möglich ist, so bekomme ich nun immerhin die Daten in IPS:

[ul]
[li]Aussentemperatur
[/li][li]Eingestellte Soll-Temperatur
[/li][li]Boiler-Temperatur
[/li][li]Rücklauf-Temperatur
[/li][li]Modulationswert
[/li][li]Brenner An/Aus
[/li][li]Fehler
[/li][li]
[/li][/ul]

Für jemanden der eigentlich immer nur in deutlich höheren Schichten programmiert war das „Bit-geschiebe“ eine echte Herausforderung - aber nun läuft es. Ein Raspberry ist per USB mit dem Gateway verbunden und ein Python-Skript erledigt die serielle Kommunikation und Dekodierung der Nachrichten. Minütlich übergibt es die gesammelten Daten dann per HTTP-Post an IPS.

Hi,

ich bin auch am überlegen mir so ein Gateway zu kaufen. Würdest du deinen Code (Für den Raspberry PI sowie IPS) zur Verfügung stellen?
Lesen würde mir vorerst schon einmal reichen. Schreiben dann in einem spätern Schritt.

Vielen Dank und viele Grüße
Christian

Ja, kann ich Dir dann gerne geben:


#!/usr/bin/env python
import serial, time, json, urllib, urllib2, logging, logging.handlers, os, sys

# Create PID
pid = str(os.getpid())
pidfile = "/var/run/opentherm.pid"

if os.path.isfile(pidfile):
    print "%s already exists, exiting" % pidfile
    sys.exit()
else:
    file(pidfile, 'w').write(pid)

# Initialize logging
my_logger = logging.getLogger('MyLogger')
my_logger.setLevel(logging.DEBUG)
handler = logging.handlers.SysLogHandler(address='/dev/log')
my_logger.addHandler(handler)
my_logger.info("OpenTherm Gateway started ...")

setpoint_temp = 0.0
outside_temp = 0.0
modulation_level = 0.0
return_water = 0.0
boiler_temp = 0.0
flame_status = 0
ch_mode = 0
fault = 0
control_setpoint = 0.0
start = time.time()


def getf88(data):
        try:
                firstbit = int(data[:1])
                if firstbit > 7:
                        # negativ!
                        deci = int(data,16)
                        print deci
                        temp = ((65536.0-deci)/256.0)*-1.0
                else:
                        # positiv
                        deci = int(data,16)
                        temp = (deci / 256.0)
                return temp
        except Exception, e:
                # Das ging schief weil 'anders' negativ
                deci = int(data,16)
                temp = ((65536.0-deci)/256.0)*-1.0
                return temp

def getflag8(data, bit):
        # 8-bit HEX data and the deserved bit position
        scale = 16 ## equals to hexadecimal
        num_of_bits = 8
        bitmask = bin(int(data, scale))[2:].zfill(num_of_bits)
        position = (1 + bit) * -1
        return bitmask[position]

def send_outdoor_temp(ot):
        global ser, my_logger
        ot = float(ot)
        if (ot < 990):
                command = "OT=" + str(ot)
                ser.write(command)
                my_logger.info("OpenTherm Aussentemp:" + command) 

def send_json():
        global my_logger
        try:
                out = {"OT":outside_temp,"ML":modulation_level,"BT":boiler_temp,"RW":return_water,"ERR":fault,"FS":flame_status,"CHM":ch_mode, "CS":control_setpoint,"RS":setpoint_temp}
                out = json.dumps(out)
                parameter = {"json":out}
                data = urllib.urlencode(parameter)
                request = urllib2.Request("http://IPS-IP:82/user/opentherm/data.php", data)
                response = urllib2.urlopen(request)
                outtemp = response.read()
                send_outdoor_temp(outtemp)
                my_logger.info("OpenTherm " + out)
        except Exception, e:
                my_logger.exception(e)
        #print response


ser = serial.Serial("/dev/ttyUSB0")  # open first serial port
#print ser.portstr       # check which port was really used
while True:
        line = ser.readline() 
        sender = line[:1]
        id = line[3:5]
        data = line[5:9]
        try:
                id = int(id, 16)
        except Exception, e:
                my_logger.exception("OpenTherm Invalid ID found. Received: " + line)
                id = 999 # If no valid ID is found we use a fake one
        
        if id == 27 and sender == 'B':
                # Outside Temp.
                outside_temp = getf88(data)
        elif id == 1 and sender == 'T':
                control_setpoint = getf88(data)
        elif id == 16 and sender == 'T':
                setpoint_temp = getf88(data)
        elif id == 17 and sender == 'B':
                # Modulation Level
                modulation_level = getf88(data)
        elif id == 25 and sender == 'B':
                # Boiler Water Temp
                boiler_temp = getf88(data)
                #print "RAW: " + line +"|Val:"+str(boiler_temp)
        elif id == 28 and sender == 'B':
                # Return Water Temp
                return_water = getf88(data)
        elif id == 0 and sender == 'B':
                # Flame State, Faults, Central Heating Mode
                lower = data[2:]
                flame_status = getflag8(lower, 3)
                fault = getflag8(lower, 0)
                ch_mode =getflag8(lower, 1)
        # Send about every Minute
        now = time.time()
        if (now-start) > 60:
                send_json()
                start = now

#print sender
#print id
#print line
ser.close()  

Hi Titus,

hab mir das Teil jetzt endlich auch mal bestellt und warte auf die Lieferung.
Bist du etwas weiter gekommen? Würdest du evtl. auch den IPS Code (PHP) posten?
Läuft der Python Code bei dir auf einer Linux Maschine (so sieht es jedenfalls aus)?
Da IPS auf Windows läuft wäre es natürlich schön ohne den Umweg auszukommen. Wenns nicht geht muss ein Raspberry PI herhalten.

Vielen Dank und viele Grüße
Chris

Moin Spaceguy,

klar kann ich Dir gerne auch den PHP-Code von IPS geben. Die PHP-Datei liegt unter $IPS\webfront\user\opentherm\data.php:

<?php
$vals = json_decode($_POST['json']);
//IPS_LogMessage("Opentherm",print_r($vals,true));

SetValueFloat(57587  /*[Erdgeschoss\HWR\Elco Thision Therme\Aussentemperatur]*/, $vals->OT);
SetValueFloat(30063  /*[Erdgeschoss\HWR\Elco Thision Therme\Raum Soll]*/, $vals->RS);
SetValueFloat(10244  /*[Erdgeschoss\HWR\Elco Thision Therme\Boiler Temperatur]*/, $vals->BT);
SetValueInteger(27648  /*[Erdgeschoss\HWR\Elco Thision Therme\Modulation]*/, $vals->ML);
if ($vals->RW) {
	// Die Therme bzw. das Gateway senden gerne zwischendurch mal 0, was natürlich quatsch ist.
	SetValueFloat(29877  /*[Erdgeschoss\HWR\Elco Thision Therme\Rücklauftemperatur]*/, $vals->RW);
}
SetValue(36569  /*[Erdgeschoss\HWR\Elco Thision Therme\Brenner läuft]*/, $vals->FS);
SetValue(29831  /*[Erdgeschoss\HWR\Elco Thision Therme\Fehler]*/, $vals->ERR);
SetValueFloat(11754  /*[Erdgeschoss\HWR\Elco Thision Therme\Wasserdruck]*/, $vals->PRESS);
SetValueFloat(32487  /*[Erdgeschoss\HWR\Elco Thision Therme\Raum Ist]*/, $vals->RT);
SetValueInteger(47905  /*[Erdgeschoss\HWR\Elco Thision Therme\Letzte Aktualisierung]*/, time());
?>

Das Gateway ist bei mir mit einem Raspi verbunden und der läuft natürlich mit Linux. Das Python-Skript sollte trotzdem auch unter Windows laufen, wobei Du natürlich die Pfade an Windows anpassen musst. Python for Windows findest Du hier.

Leider kann ich immer noch keine Wunschtemperatur an die Therme schicken, weil mein Siemens QAA73 die eingehenden Nachrichten schlicht ignoriert. Hatte mir deswegen ein Remeha Isense Raumthermostat gekauft. Leider ist OpenTherm nur dem Namen nach offen, denn das Rhema-Thermosta und meine Elco-Therme sind nicht kompatibel zueinander. Es geht einige Minuten, dann zeigt die Therme nur noch eine Fehlermeldung an. Ein freundlicher Mensch aus dem Domoticaforum hilft mir zwar beim debuggen, nur leider habe ich aktuell keine Zeit mich darum zu kümmern. Deswegen habe ich wieder das Siemens-Thermostat dran.

Hallo,

gibt es weitere Erfahrungen mit dem OpenTherm Anschluss in Verbindung mit einer Vitovent 300 (= Brink Renovent = Wolf CWL300…) ?

Vor kurzem dachte ich mir, jetzt wäre es klasse die Lüftung von der Leistung her - per VPN- hochzuregeln.
Jetzt bei der Hitze haben wir tagsüber die Lüftung auf minimal laufen… während wir unterwegs waren, kam ein „kühlendes“ starkes Gewitter. Da wäre es klasse gewesen, die Lüftung - von unterwegs aus - hochregeln zu können…

Hat sich damit schon jemand näher beschäfigt?
Was ich mir noch als Frage stelle, was passiert wenn die konventionelle Fernbedienung auf MODUS „REDUZIERT“ steht und man die Anlage per Opentherm Bus Gateway auf NORMAL/PARTY umstellt?

Aus dem KNX Forum habe ich zufällig gelesen:

Ich habe eine Vitovent 300 von 2012. Die Steuerung ist per OpenTherm angeschlossen.

Dann habe ich einen Gateway gekauft ( Controlling the central heating system) und die Firmware angepasst. Es gibt jetzt ein Kommando PR=M um den Modus abzufragen und ein MO=<value> um ihn zu setzen.

Der Gateway passt dann die OpenTherm Nachrichten an, spielt also Man in the Middle. Die alte Steuerung bleibt dabei völlig erhalten.

Die Steuerung habe ich dann an einen Raspberry per USB angeschlossen. Der Raspberry hat ein Programm laufen, dass die seriellen Kommandos des Gateways interpretiert und gegebenfalls ein Kommando einschleußt.

Die KNX Anbindung habe ich mit meiner eigenen Implementierung ( KNX Library ) realisiert. Die Software hört auf eine KNX Gruppenadresse und schreibt auf eine zweite.

Die beiden Gruppenadressen sind dann in der ETS mit dem Gira TS3Plus verbunden. Dort ist die manuelle Lüftersteuerung aktiviert. Auf dem Display sieht man dadurch den Zustand des Lüfters. Eine der Wippen kann dann genutzt werden um die Vitovent umzuschalten.

Vom drücken des Tasters bis zur Anzeige auf dem TS3 vergehen etwa 2 Sekunden. Diese Verzögerung ist vor allem durch die Kommunikation mit der Vitovent bedingt.

Zusätzlich und völlig optional zeige ich den Zustand der Vitovent auch noch auf einer internen Webseite an. Das ist aber schon fasst wieder ein Thema für sich.