Ansteuerung einer Heizung über COM oder LON-Bus

Hallo Forum,

super Arbeit die Ihr hier leistet.

Ich hätte gerne mal Eure Meinung zu einem meiner noch zu lösenden Probleme in meiner Haustechnik.

In meinem Häusschen werkelt ein Heizsystem der Firma Paradigma. Die Heizung besteht aus einem zentralem Schichtenspeicher, Vakuumröhren auf dem Dach und für die kalten Tage eine Junkers Gastherme zum zuheizen.
Gesteuert wird das ganze über eine erweiterbare Steuereinheit des Herstellers, genannte MES.
Dahinter verbirgt sich ein Modulgehäuse mit 5 Slots. Zur Zeit sind die Module Kesselsteuerung (zur Ansteuerung der Heiztherme), ein Heizungsmodul (zur Regelung des Schichtenspeichers, Heizung und Warmwasser), ein Solarmodul, zentrales Netzteil und ein COM-Modul installiert. Mit Hilfe des COM-Moduls kann man per seriell angeschlossenem PC und der passenden Software (genannt PCMS) die Parameter der Heizungssteuerung ansehen und ändern. Die einzelnen Module sind über einen LON-Bus miteinander verbunden. Das COM-Modul greift über diesen LON-Bus auf die anderen Modul-Daten zu.
Genau das hätte ich aber gerne in die IPS eingebunden bzw. von der IPS aus im Zugriff. Hier würde ich gerne mal Eure Meinung hören, wie man die Kommunikation zwischen IPS und MES am besten realisiert. Ich habe bisher zwei Ansätze:

Mein erster Ansatz war , ich greife an dem seriellen Bus die Kommunikation ab, emuliere sozusagen die Orginalsoftware mit der COM-Instance der IPS. In einem ersten Schritte habe ich mir erst mal den Datenfluss zwischen COM-Modul der Heizung und der org. Software angesehen ( mit einem seriellen Port Monitor - HDD). Allerdings komme ich mit der Identifizierung des verwendeten Protokolls nicht weiter. Ich hab klein angefangen, mir nur einen Heizungsparameter anzeigen lassen (also lesend vom Modul). Aber hier wird leider kein klartext geredet. Oder habt Ihr eine Idee, wie die HEX-Zeichenfolge:

22 12 74 01 0E den Flieskommawert +47,24 darstellen soll (Vorlauftemperatur)

Weiterhin gestaltet sich die Anbindung via IPS hier, denke ich, ziemlich schwierig, da die beiden Seiten wirklich gegenseitig Daten austauschen. Eine Messwertabfrage wird so z.B. mit dem HEX-Code (02 22 00 00 24) eingeleitet. Darauf antwortet die MES mit HEX (02 06 22 00 2A). Dann kommt erst der eigentliche Abfragebefehl einer Variable, HEX (03 77 0A) mit dem Variablenindex HEX (16 00 9A). Dann kommen Antworten wie oben beschrieben (der Flieskommawert).
Kann ich so eine Kommunikation überhaupt in der IPS nachstellen ?

Mein zweiter Ansatz ist jetzt vielleicht in die Kommunikation der MES mit Hilfe eines LON-Bus- Adapters einzusteigen. Hab ich im Internet bereits in Form von Seriell, USB und Internetserver gefunden. Hat hier jemand von Euch Erfahrungen wie das mit der IPS aussieht ?

Das war ja erst mal ne Menge Text, ich hoffe ich habs nicht zu umständlich ausgedrückt.

Grüße

winni

Dein Ansatz mit dem ComPort ist schon der richtige und bestimmt auch der einfachste.

Was dir zu deinem Glück fehlt ist das Protokoll. Da müsstest du mal beim Hersteller direkt oder über deinen Installateur bei dem mal Nachfragen lassen, ob du die bekommst. Wenn du ganz viel Glück hast, rücken die das raus.

Mit allen anderen Adapter wird es auch nicht einfacher. (Klartext wirst du nirgends sehen)

Falls du den Reverse Engineering nimmt:

Die Bytes die hin und hergeschickt werden müsstest du öfters für paar Temperaturwerte abfragen. Dann siehst du was Konstant bleibt und welche Werte sich ändern. Die sich ändernden Werte werden dann deine Temperatur darstellen. (Wird entweder 2 oder 4 Bytes sein)

Nun musst du mit den Bytes rausfinden, in welchem Standard die Sache kodiert ist und dann hast du die Zahl :slight_smile:

Evtl musst du gucken, ob am Ende eine Prüfsumme sein könnte.

paresy

HEX-Code (02 22 00 00 24)

da fühlt man sich wieder wie zur MOSC-Zeit… :smiley:

PS: für die, die damit nix anfangen können, MOSC bedeutet „Modified Original Smart Card“ und kommt aus den Anfängen des verschlüsselten Digitalfernsehens

Aber die Zeiten sind längst vorbei…

22 12 74 01 0E den Flieskommawert +47,24

also hab jetzt mal genauer hingesehen…

die 47,24 ist ein float, d.h. er wird bei der Übertragung in Mantisse und Exponent zerlegt. Allerdings sind diese normalerweise binär codiert.

Hierbei ergibt sich jedoch bei Umrechnung folgendes:
0x1274 ergibt in dez. 47,24 >> das halte ich nicht für einen Zufall

Schau mal andere Werte nach oder poste sie hier.

Gruß
Fabian

und die Quersumme von 12 74 ist 0E - womit auch die Checksumme durchaus Sinn geben würde. Ach, wenn die Dinge nur immer so einfach wären…:wink:

prof hat recht… zeig doch noch ein paar her… Ist bislang alles nur Vermutung.

Toni

Hallo Leute,

also erst mal vielen, vielen Dank für die tollen Antworten.

@paresy:
Aus Deiner Antwort schliesse ich, Du würdest hier mit dem Reverse-Engineering weiter machen. Also hat die Idee mit dem LON-Bus keinen Sinn ? Kriegt man denn über die IPS-Com-Instance eine bidirectionale Kommunikation (Send-Befehl, zum Werte anfordern / Empfang und Codierung der von der MES gesendeten Werte) so ohne weiteres hin. Ihr müsst wissen, ich habe quasi Null Erfahrung in PHP. Meine letzten Programiererfahrungen kommen aus dem Studium, is lange her, und war damals noch in Turbo-Pascal…
Aber ich denke, Du hast recht, Prof und Tonic1024 haben das Protokoll ja schon fast identifiziert. Beim Hersteller anzufragen traue ich mich erlich gesagt noch nicht so richtig. Hier war kein Installateur betraut, ich habe die ganze Technik selber über den Großhandel bezogen und selbst eingebaut.

@prof @tonic1024:
Super, ich glaub ihr seit hier genau richtig. Hier mal die kompletten Kommunikations-Mitschnitte für das Abfragen von drei unterschiedlichen Variablen:

1.Variable (Aussentemperatur: TA Wert: 3,55)
Request:
02 22 00 00 24
Answer: 02 06 22 00 2A
Request:
03 77 0A 16 00 9A
Answer:
05 57 0A 16 01 63 00 E0

2.Variable (Vorlauftemp.: TV Wert 47,24)
Request:
02 22 00 00 24
Answer:
02 06 22 00 2A
Request:
03 77 0A 22 00 A6
Answer:
05 57 0A 22 12 74 01 0E

3.Variable (Vorlauf_soll : TVsoll Wert 48,31)
Request:
02 22 00 00 24
Answer:
02 06 22 00 2A
Request: 03 77 0A 21 00 A5
Answer: 05 57 0A 21 12 DF 01 78

und hier als letztes noch mal der Mitschnitt für das Abfragen von zwei Variablen gleichzeitig:

Variable TVs=46,43 sowie TVsoll=48,31
Request:
02 22 00 00 24
Answer:
02 06 22 00 2A
Request:
03 77 0A 22 00 A6
Answer:
05 57 0A 22 12 23 00 BD
Request:
03 77 0A 21 00 A5
Answer:
05 57 0A 21 12 DF 01 78

Bisher habe ich das wie folgt interpretiert:
Der Request: 02 22 00 00 24 ist eine Art von Einleitung der Kommunikation.
Er wird immer gleich bestätigt, mit der Answer: 02 06 22 00 2A .
Das Kommando zum Abfragen einer Variable scheint der 1. Teil des Requests: 03 77 0A 16 00 9A (also 03 77 0A) zu sein, da er immer in allen Variablenabfragen erscheint. Der zweite Teil des Kommandos steht also wahrscheinlich für die Variable, die abgefragt werden soll (hier: 16 00 9A)

Danach sind die Variablen identifiziert:

TA : 16 00 9A
TV : 22 00 A6
TVsoll : 21 00 A5

Der Variablen-Wert steht immer in einer Answer, die mit 05 57 0A anfängt und dann den Inhalt enthält, wie z.B. in meinem ersten Feed beschrieben.

Mein größtes Problem, ich habe keine Ahnung wie ich die IPS dazu bekomme, die decodierung wie Ihr sie beschrieben habt in eine IPS-Variable vorzunehmen.

Habt Ihr eine Idee ?

Grüße

winni

Hi nochmal,

noch ein Nachtrag:

Die Float-Werte, die ich oben angegeben habe sind bisher immer positive Werte. Sie könneten natürlich auch negative Werte darstellen (TA unter Null, z.B.). Dafür habe ich jetzt leider keinen aktuellen Mitschnitte, ist halt ein sehr warme November :slight_smile: . Habt Ihr eine Idee, wie der Hersteller das mit dem Vorzeichen geregelt hat ?

Grüße

winni

Ich hab das mal eben durch meine „Analyzer-Software“ gejagt und denke das könnte so ausschauen:

 
// Variable TVs=46,43   sowie  TVsoll=48,31
//Request: 
02 22 00 00 24        // Init: "Hallo? Ist da wer?"
//Answer: 
02 06 22 00 2A        // Init: "Wer stört?"  
//Request: 
03 77 0A 22 00 A6   //  "Fein, dann lass mal die TVs rüberwachsen"
//Answer: 
05 57 0A 22 12 23 00 BD   // "TVs ist 12 23"  
//Request: 
03 77 0A 21 00 A5         // "Wo wir grade schnacken... Haste auch die TVsoll?"
//Answer: 
05 57 0A 21 12 DF 01 78  // "Klar, TVsoll ist 12 DF"

Der Init String scheint immer der selbe zu sein. Da du sagst, dass deine Anlage modular aufgebaut ist könnte dort noch die Adresse des moduls drin stecken (Modul 22?). Darüber können wir hier nix feststellen. Die letzten beiden Ziffern sind immer die Checksumme. Das ist auch durchaus so üblich.

03 77 0A 22 00 A6 ist eine Anfrage. dabei könnte 03 77 oder 03 77 0A einfach bedeuten „request“ und 22 oder 0A 22 (was ich für wahrscheinlicher halte) den Request spezifizieren. In diesem Fall die TVs (was ist eine TVs?). 00, denke ich mal, ist eine Art Füllzeichen für Details. Kann man nix zu sagen - ist wahrscheinlich aber auch irrelevant.

05 57 könnte für „Antwort“ stehen wobei 0A 22 - das kennen wir schon - die Antwort spezifiziert. Wir haben nach TVs gefragt und bekommen für TVs ne Antwort, also für 0A 22.

Die Folgenden zwei Byte sind der Wert. 12 23(hex) -> 4643(dez).

Und genauso bei TVsoll…

negative Zahlen werden oft mit invertiertem MSB gekennzeichnet und dann „rückwärts gezählt“. Also wäre FF F4 in hex -0.12 dezimal. Ob der Hersteller das so macht ist aber die Frage…

Toni

Alsooooo,

das würde bedeuten, ich müsste die Bytes hier mehr in zweier Gruppen sehen:

Der Request-Befehl wäre also: 03 77

Die Antwort darauf wäre: 05 57

Die Variablen hätten die Bezeichnung:

TV : 0A 22 (TVs war übrigens ein kleiner Tippfehler von mir, meinte TV)
TVsoll : 0A 21
TA : 0A 16

Dann jeweils zwei Bytes für den eigentlichen Wert.
Blos das mit den letzten beiden Bytes in der Antwort ist mir noch nicht ganz klar. Das mit der Prüfsumme (im Beispiel der 2. Variable) 0E scheint doch nur ein Zufall gewesen zu sein. In der 1. und 3. Variable haut die Quersumme hier nicht hin (wenn mich meine Mathematik-Kenntnisse hier nicht trüben :slight_smile: .

Alsooooo,das würde bedeuten, ich müsste die Bytes hier mehr in zweier Gruppen sehen:

genau, 16 Bit ist ja nicht sooo ungewöhnlich, oder?

[…]haut die Quersumme hier nicht hin[…]

Die 00 hinten gehört mit zur checksumme!

Quersumme aus „05 57 0A 21 12 DF“ ergibt „01 78“.

22 12 74 01 0E“ ist so allein nicht gültig. Um das festzustellen ist eine Checksum ja da… „05 57 0A 22 12 74“ ergibt „01 0E“

Du hast uns den Anfang der Datenreihe unterschlagen in deinem 1. Post… Natürlich zieht man dann falsche Schlüsse :rolleyes:

Toni

genau, darüber hatte ich auch gegrübelt…

Aber jetzt isses klar!

Na Spitze Leute,

jetzt hätten wir das Protokoll identifiziert.

Aber nun meine große Frage, wie kriege ich das mit der IPS Software geschnackt ?

Grüße

winni

auf die selbe Weise wie Hmpf99 mit seinem Denon schnackt.

Toni

Hallo nochmal,

bin jetzt gerade dabei ein passendes Programm zu stricken. Anregungen gibt es ja wirklich genug hier im Forum.

Ein kleines Problem habe ich aber noch. Fällt Euch vielleicht ein Lösung (PHP-Function) für das Berechnen der Checksum ein. Mir ist bei Euren obrigen Beiträgen noch nicht mal klar wie die Checksumme gebildet wurde. Ich habs bisher mit CRC16, CRC32, LRC und XOR (16 bitweise) probiert (mit Internet Online Rechner), komme aber nicht auf die passenden Werte.

Es geht um die Zeile:

Quersumme aus „05 57 0A 21 12 DF“ ergibt „01 78“.

Viele Grüße

winni

addiere mal hex die einzelnen bytes…

05 + 57 + 0A + 21 + 12 + DF = 01 78

gibt noch eine kleine Hürde, die du umschiffen musst. Eine Zahl (Integer) in HEX darzustellen:

    
****CANCELED****
Edit:

Ach, bevor es heisst der postet nur halbfertige Codes, die nicht funktionieren… :rolleyes: Iss ja auch ne schöne Fingerübung… :wink:

        
function checksum($hex)
{
   $Value=0;
   for ($i=0; $i < StrLen($hex)/2; $i++)
      $Value=$Value+hexdec(substr($hex, $i*2, 2));

   $Value=dechex($Value);
   $Len=4 - StrLen($Value);
   for ($i = $Len; $i!=0; $i--)
      $Value='0'.$Value;
   return $Value;
}

$test='05570A2112DF';
print($test.checksum($test));

Toni

Mann! Seit ihr gut. :eek:

Das iss mein Job :wink:

Hi Leute,

super Vielen Dank für die Unterstützung.
Das fertige Script läuft seit gestern Abend auf meiner IPS Zuhause und liest braf 20! Variablen aus der Heizungssteuerung aus.
Wenn ich Morgen Abend Zuhause bin, poste ich es hier noch mal komplett, sozusagen als Abschluss dieses Threads, falls noch mal ein andere, vor einer vergleichbaren Problematik steht.

Bis Morgen…

Grüße
winni

Hallo nochmal,

so wie versprochen, hier das fertige Script. Es läuft bei mir alle 10 Minuten durch und holt die aktuellen Werte aus der Heizung. Das sind u.a. Temperaturen von Aussen, Kesselvor-rücklauf, Solarvor-rücklauf,Speicher oben/mitte/unten, Brennerstarts, Brennerstatus aber auch so interessantes wie Solarer Gewinn, tägliche solare Leistung usw.

<?
/*
*******************************
 IP-SYMCON Event Scripting
*******************************
File     : getMESdata.ips.php
Trigger  : 
Interval : 
*/
//Variablendefinitionen:
//MES-Commands
$cmd_init=chr(2).chr(0x22).chr(0).chr(0).chr(0x24);
$cmd_init_answer=chr(2).chr(6).chr(0x22).chr(0).chr(0x2A);
$cmd_read_var=chr(0x03).chr(0x77);
$cmd_var_is=chr(0x05).chr(0x57);
//Definition der MES Variablen, die geholt werden sollen
//Variablen-Array mit Inhalt: IPS-Var-Name,MES-Code,VarType
$MES_VarSet=array();
$VarSetNumber=20;
$MES_VarSet[0]=array("TV",chr(10).chr(0x22),'float');
$MES_VarSet[1]=array("TVsoll",chr(10).chr(0x21),'float');
$MES_VarSet[2]=array("TA",chr(10).chr(0x16),'float');
$MES_VarSet[3]=array("TWO",chr(10).chr(0x19),'float');
$MES_VarSet[4]=array("TWOsoll",chr(10).chr(0x1A),'float');
$MES_VarSet[5]=array("HKM_Position",chr(10).chr(0x24),'float');
$MES_VarSet[6]=array("HKM_Mode",chr(10).chr(0x0C),'integer');
$MES_VarSet[7]=array("SL",chr(8).chr(0x30),'float');
$MES_VarSet[8]=array("TG",chr(8).chr(0x2F),'float');
$MES_VarSet[9]=array("TWU",chr(8).chr(0x21),'float');
$MES_VarSet[10]=array("TSA",chr(8).chr(0x34),'float');
$MES_VarSet[11]=array("TSE",chr(8).chr(0x0E),'float');
$MES_VarSet[12]=array("SG",chr(8).chr(0x2E),'float');
$MES_VarSet[13]=array("PSO",chr(8).chr(0x10),'integer');
$MES_VarSet[14]=array("TPO",chr(4).chr(0x17),'float');
$MES_VarSet[15]=array("TPOsoll",chr(4).chr(0x18),'float');
$MES_VarSet[16]=array("TPU",chr(4).chr(0x1C),'float');
$MES_VarSet[17]=array("TPV",chr(4).chr(0x2B),'float');
$MES_VarSet[18]=array("B1_starts",chr(4).chr(0x21),'integer');
$MES_VarSet[19]=array("B1_Mode",chr(4).chr(0x1A),'integer');
//Konstanten:
define ('COM',13986);
define ('Register',12671);
define ('RegVar','Com1Response');

function ChecksumStr($checkstr) {
  $res=0;
  $resstr='';
  for ($i=0; $i<strlen($checkstr);$i++) {
    $res = $res+ord($checkstr{$i});
    }
  $resstr=chr(floor($res/256)).chr($res-(floor($res/256)*256));
  return $resstr;
  }

function HexString($AscStr) {
  $res='';
  for ($i=0; $i<strlen($AscStr); $i++) {
    $res=$res." ".dechex(ord(substr($AscStr,$i,1)));
    }
  return $res;
  }

function GetValueMES($para) {
  global $MES_wert;
  global $cmd_read_var;
  global $cmd_var_is;
  SetValueString(RegVar,'');
  //Request Heizungsvariable
  $send=$cmd_read_var.$para.ChecksumStr($cmd_read_var.$para);
  ComPort_SendText(COM,$send);
  sleep(1);
  //Hole Antwort von MES
  $data=GetValueString(RegVar);
  //reset buffer
  SetValueString(RegVar,'');
  $MES_wert=0;
  if (strlen($data)==0) {
    //no data
    echo "Keine Antwort vom Interface
";
    return false;
  } else {
    if (substr($data,0,2)==$cmd_var_is) {
      if (ChecksumStr(substr($data,0,6))==substr($data,6,2)) {
        $MES_wert=((ord($data{4})*256)+ord($data{5}));
        return true;
      } else {
      //Checksummenfehler
      echo "Falsche Checksumme bei der Antwort: ".HexString($data)."
";
      echo "Checksumme ist: ".HexString(ChecksumStr(substr($data,0,6)))."
";
      return false;
      }
    } else {
      //falsche Antwort
      return false;
      echo "Falsche Antwort: ".HexString($data)."
";
    }
  }
}

//Start des Ablaufs
settype($MES_wert,"double");
SetValueString(RegVar,'');
//Initstring senden
ComPort_SendText(COM,$cmd_init);
echo "Initialisierung gesendet
\r";
sleep(1);
$data=GetValueString(RegVar);
SetValueString(RegVar,'');
if ($data==$cmd_init_answer) {
  //Init o.k. Beginn der Variablenabfrage
  echo "Init erfolgreich
\r";
  for ($i=0;$i<$VarSetNumber;$i++) {
     if (GetValueMES($MES_VarSet[$i][1])==true) {
       if ($MES_VarSet[$i][2]=='float') {
         $MES_wert=$MES_wert/100;
         if (SetValueFloat($MES_VarSet[$i][0],$MES_wert)==false) {
           echo "Fehler bei der Variablenuebergabe an IPS
\r";
           }
         }
       if ($MES_VarSet[$i][2]=='integer') {
         if (SetValueInteger($MES_VarSet[$i][0],$MES_wert)==false) {
           echo "Fehler bei der Variablenuebergabe an IPS
\r";
           }
         }
       echo $MES_VarSet[$i][0]." = $MES_wert
";
       } else {
       //Fehler beim Abfragen der Variablen
       echo "Fehler beim Abfragen der Variable ".$MES_VarSet[$i][0]."
";
       }
     }
  } else {
    //Init nicht o.k. keine Abfrage
    echo "Kommunikationsfehler im Init-Bereich
";
    echo "Antwort: ".HexString($data)." : ".strlen($data)." Byte";
  }


?>

Also ich habe jetzt z.Z. noch einige Sicherheitsabfragen drin. Wenn alles weiterhin sauber läuft, kann man den Code vielleicht noch ein bisschen zusammenkürzen.

Bitte nicht Lachen, ich habe seit 15 Jahren kein Programmchen mehr geschrieben. Wie gesagt, das war damals noch in Turbo-Pascal. Aber irgendwie komme ich mit dem PHP relativ gut zurecht.

Kommentare zum Programmierstil sind sehr willkommen. Wie gesagt Erfahrungen liegen hier leider noch nicht so richtig vor. Aber ich bin davon überzeugt, bei der einfachen Art-und-Weise wie das mit der IPS funktioniert und dem spitzen Support hier, kann man bestimmt noch einiges machen.

Also, vielen Dank nochmal.

Grüße

winni