Ankündigung

Einklappen
Keine Ankündigung bisher.

Neues Plugin ComfoAir (KWL Wohnraumlüftung Zehnder, Paul, Wernig)

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    #31
    Zitat von shs2 Beitrag anzeigen
    Allerdings scheint es, dass die Schnittstelle aus dem Tritt gerät und im zeitlichen Verlauf immer mehr Fehler und soger exeptions liefert .
    Hier mal eine längere Aufzeichnung.
    Guten Morgen!

    Lustig, schau dir mal die Logs an, welche Antworten zurückkommen.
    Beim ersten Mal passt es noch, bei der zweiten Antwort ist vor dem eigentlichen Telegramm ein 0xFF, das da eigentlich nicht hingehört und daher das Ganze außer Tritt bringt.

    Beim zweiten Shot hast du sogar einige 0xFF im Datenstrom...

    Jetzt ist hald die Frage, ist das ein Problem deines Konverters? Oder ein Spezifikum der ComfoAir 500 (ACK Zeichen??), schaut aber merkwürdig aus...

    Kannst du vielleicht mal statt dem Plugin das Herkules RS232 Tool verwenden, ein paar Befehle laut Protokoll abschicken und schauen, wann/ob da 0xFF zusätzlich daher kommen?

    Edit: Ich korrigiere mich, ACK kann es nicht sein, da öfters in deinem Log auch keine zusätzlichen 0xFF da sind. Muss fast an deinem Konverter/Schnittstelle liegen, korrekt kann das nicht sein.

    LG Stefan

    Kommentar


      #32
      Hallo Stefan.

      am PC mit Hercules sieht es recht gut aus - ich habe keine FF gefunden. Allerdings kommt die Antwort
      immer mehrfach

      Habe in diesem Beispiel nacheinander
      3* 07 F0 00 85 00 32 07 0F
      und 2* 07 F0 00 87 00 34 07 0F an die Comfoair gesendet

      Jede Antwort wird aber immer 5* zurückgeliefert.
      Und dazwischen findet sich 07 f3 oder 07 f3 07 ( komisch warum ACK hier unterschiedlich ausfällt)

      Lässt das bzw die Mehrfachsendung Deinen Eingangsbuffer evt. überlaufen?

      Strukturiert
      Code:
      {07}{F0}{00}{85}{00}{32}{07}{0F}
      {07}{F3}
      {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}
      {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}
      {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}
      {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}
      {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}
      
      {07}{F0}{00}{85}{00}{32}{07}{0F}
      {07}{F3}
      {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}
      {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}
      {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}
      {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}
      {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}
      
      {07}{F0}{00}{85}{00}{32}{07}{0F}
      {07}{F3}{07}
      {F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}
      {F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}
      {F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}
      {F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}
      {F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}
      
      {F0}{00}{87}{00}{34}{07}{0F}
      {07}{F3}{07}
      {F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}
      {F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}
      {F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}
      {F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}
      {F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}
      
      {F0}{00}{87}{00}{34}{07}{0F}
      {07}{F3}{07}
      {F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}
      {F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}
      {F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}
      {F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}
      {F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}
      Roh:
      Code:
      {07}{F0}{00}{85}{00}{32}{07}{0F}{07}{F3}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}{07}{F0}{00}{85}{00}{32}{07}{0F}{07}{F3}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{85}{00}{32}{07}{0F}{07}{F3}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{87}{00}{34}{07}{0F}{07}{F3}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}{F0}{00}{87}{00}{34}{07}{0F}{07}{F3}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}

      Gruß Stephan

      Kommentar


        #33
        Zitat von shs2 Beitrag anzeigen
        Hallo Stefan.

        am PC mit Hercules sieht es recht gut aus - ich habe keine FF gefunden. Allerdings kommt die Antwort
        immer mehrfach

        Habe in diesem Beispiel nacheinander
        3* 07 F0 00 85 00 32 07 0F
        und 2* 07 F0 00 87 00 34 07 0F an die Comfoair gesendet

        Jede Antwort wird aber immer 5* zurückgeliefert.
        Und dazwischen findet sich 07 f3 oder 07 f3 07 ( komisch warum ACK hier unterschiedlich ausfällt)

        Lässt das bzw die Mehrfachsendung Deinen Eingangsbuffer evt. überlaufen?

        Strukturiert
        Code:
        {07}{F0}{00}{85}{00}{32}{07}{0F}
        {07}{F3}
        {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}
        {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}
        {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}
        {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}
        {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}
        
        {07}{F0}{00}{85}{00}{32}{07}{0F}
        {07}{F3}
        {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}
        {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}
        {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}
        {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}
        {07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}
        
        {07}{F0}{00}{85}{00}{32}{07}{0F}
        {07}{F3}{07}
        {F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}
        {F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}
        {F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}
        {F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}
        {F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}
        
        {F0}{00}{87}{00}{34}{07}{0F}
        {07}{F3}{07}
        {F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}
        {F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}
        {F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}
        {F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}
        {F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}
        
        {F0}{00}{87}{00}{34}{07}{0F}
        {07}{F3}{07}
        {F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}
        {F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}
        {F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}
        {F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}
        {F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}
        Roh:
        Code:
        {07}{F0}{00}{85}{00}{32}{07}{0F}{07}{F3}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{29}{00}{25}{07}{0F}{07}{F0}{00}{85}{00}{32}{07}{0F}{07}{F3}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{85}{00}{32}{07}{0F}{07}{F3}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{84}{0A}{00}{BD}{00}{40}{56}{43}{32}{F9}{28}{00}{24}{07}{0F}{07}{F0}{00}{87}{00}{34}{07}{0F}{07}{F3}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9D}{31}{00}{20}{00}{01}{01}{00}{3B}{07}{0F}{07}{F0}{00}{87}{00}{34}{07}{0F}{07}{F3}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}{07}{F0}{00}{86}{0B}{34}{32}{A7}{9E}{31}{00}{20}{00}{01}{01}{00}{3C}{07}{0F}

        Gruß Stephan
        Das passt schon, das ACK ist nicht unterschiedlich. Jedes der Telegramme beginnt mit 07 0F, beim zweiten Block sind nur die 07er in die jeweils vorherige Zeile gehüpft. Schaut also alles normal aus.

        Das mit den mehrfachen Antworten - könnte es sein, dass deine ComfoAir die Antwort wiederholt, wenn du auf den ersten Versuch nicht gleich ACK sendest? Versuch mal im Simulator, ein ACK vorzubereiten und sofort nach der Antwort hinzuschicken.

        Das erklärt aber dann trotzdem noch nicht das Problem mit dem Plugin, da ich ja ein ACK nach der Antwort sende.

        LG Stefan

        Kommentar


          #34
          Hallo Stefan,

          Du hast natürlich Recht - da hatte ich Tomaten auf den Augen - ACK kommt zuverlässig.
          Und die Comfoair hört auch mit dem Senden auf, sobald ein ACK vom PC aus gesendet wird.
          Ich habe auf Hercules bislang nur 1* nach dem Intitialieren der Schnittstelle ein FF gesehen - das war´s.
          Nie bei der Kommunikation mit der Comfoair


          Gruß Stephan

          Kommentar


            #35
            Hallo Stefan,

            hier ein log vom bislang längsten Gutfall - ohne äussere Veränderungen. Vielleicht hilft er Dir:

            Gruß Stephan
            Angehängte Dateien

            Kommentar


              #36
              Halle Stefan,

              ich habe heute die direkte USB Verbindung abgeklemmt und einen alten Notebook als Server betrieben. Mit gleicher Hardware V.24 und RS485 habe ich keine Probleme mehr, dass das Plugin aus dem Tritt gerät.

              Ich werde meinen Zugang auf IP umstellen und gut ist (so hoffe ich).

              Hier ein typische Leseblock:
              HTML-Code:
              2013-11-30 17:47:47,387 INFO     ComfoAir-cyclic-reads ComfoAir: Triggering cyclic read command: ReadComfortTemperature -- __init__.py:log_info:527
              2013-11-30 17:47:47,393 INFO     ComfoAir-cyclic-reads ComfoAir: Preparing command ReadComfortTemperature with value None (transformed to value byte '') to be sent. -- __init__.py:log_info:527
              2013-11-30 17:47:47,399 INFO     ComfoAir-cyclic-reads ComfoAir: Successfully sent packet: 07:f0:00:8b:00:38:07:0f -- __init__.py:log_info:527
              2013-11-30 17:47:47,623 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response:  -- __init__.py:log_info:527
              2013-11-30 17:47:47,635 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response: 07:f0:00:8a:0a -- __init__.py:log_info:527
              2013-11-30 17:47:47,640 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response: 5f:54:4c -- __init__.py:log_info:527
              2013-11-30 17:47:47,645 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response: 36:51:2c:0f:2a:03:1a:49 -- __init__.py:log_info:527
              2013-11-30 17:47:47,651 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response: 07:0f -- __init__.py:log_info:527
              2013-11-30 17:47:47,657 INFO     ComfoAir-cyclic-reads ComfoAir: Successfully received response: 07:f0:00:8a:0a:5f:54:4c:36:51:2c:0f:2a:03:1a:49:07:0f -- __init__.py:log_info:527
              2013-11-30 17:47:47,663 DEBUG    ComfoAir-cyclic-reads ComfoAir: Corresponding read command: 00:8b:00, decoded data: 5f:54:4c:36:51:2c:0f:2a:03:1a (raw: 5f:54:4c:36:51:2c:0f:2a:03:1a) -- __init__.py:log_debug:523
              2013-11-30 17:47:47,668 DEBUG    ComfoAir-cyclic-reads ComfoAir: Matched command ReadComfortTemperature and read transformed value 22.0 (raw value was 84) from byte position 2 and byte length 1. -- __init__.py:log_debug:523
              2013-11-30 17:47:47,673 INFO     ComfoAir-cyclic-reads ComfoAir: Triggering cyclic read command: ReadExhaustAirTemperature -- __init__.py:log_info:527
              2013-11-30 17:47:47,678 INFO     ComfoAir-cyclic-reads ComfoAir: Preparing command ReadExhaustAirTemperature with value None (transformed to value byte '') to be sent. -- __init__.py:log_info:527
              2013-11-30 17:47:47,683 INFO     ComfoAir-cyclic-reads ComfoAir: Successfully sent packet: 07:f0:00:85:00:32:07:0f -- __init__.py:log_info:527
              2013-11-30 17:47:47,825 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response:  -- __init__.py:log_info:527
              2013-11-30 17:47:47,837 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response: 07:f0:00:84:0a -- __init__.py:log_info:527
              2013-11-30 17:47:47,843 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response: 00:13:00 -- __init__.py:log_info:527
              2013-11-30 17:47:47,848 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response: 3c:56:43:2e:f9:21:00:6b -- __init__.py:log_info:527
              2013-11-30 17:47:47,854 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response: 07:0f -- __init__.py:log_info:527
              2013-11-30 17:47:47,860 INFO     ComfoAir-cyclic-reads ComfoAir: Successfully received response: 07:f0:00:84:0a:00:13:00:3c:56:43:2e:f9:21:00:6b:07:0f -- __init__.py:log_info:527
              2013-11-30 17:47:47,865 DEBUG    ComfoAir-cyclic-reads ComfoAir: Corresponding read command: 00:85:00, decoded data: 00:13:00:3c:56:43:2e:f9:21:00 (raw: 00:13:00:3c:56:43:2e:f9:21:00) -- __init__.py:log_debug:523
              2013-11-30 17:47:47,871 DEBUG    ComfoAir-cyclic-reads ComfoAir: Matched command ReadFreshAirTemperature and read transformed value 10.0 (raw value was 60) from byte position 4 and byte length 1. -- __init__.py:log_debug:523
              2013-11-30 17:47:47,876 DEBUG    ComfoAir-cyclic-reads ComfoAir: Matched command ReadIntakeAirTemperature and read transformed value 3.0 (raw value was 46) from byte position 7 and byte length 1. -- __init__.py:log_debug:523
              2013-11-30 17:47:47,881 DEBUG    ComfoAir-cyclic-reads ComfoAir: Matched command ReadExtractAirTemperature and read transformed value 23.0 (raw value was 86) from byte position 5 and byte length 1. -- __init__.py:log_debug:523
              2013-11-30 17:47:47,886 DEBUG    ComfoAir-cyclic-reads ComfoAir: Matched command ReadExhaustAirTemperature and read transformed value 13.5 (raw value was 67) from byte position 6 and byte length 1. -- __init__.py:log_debug:523
              2013-11-30 17:47:47,891 DEBUG    ComfoAir-cyclic-reads ComfoAir: Matched command ReadBypassPercentage and read transformed value 0 (raw value was 0) from byte position 1 and byte length 1. -- __init__.py:log_debug:523
              2013-11-30 17:47:47,900 INFO     ComfoAir-cyclic-reads ComfoAir: Triggering cyclic read command: ReadExtractAirRPM -- __init__.py:log_info:527
              2013-11-30 17:47:47,896 DEBUG    Scheduler    ComfoAir-cyclic-reads next time: 2013-11-30 17:48:17+01:00 -- scheduler.py:_next_time:289
              2013-11-30 17:47:47,909 INFO     ComfoAir-cyclic-reads ComfoAir: Preparing command ReadExtractAirRPM with value None (transformed to value byte '') to be sent. -- __init__.py:log_info:527
              2013-11-30 17:47:47,915 INFO     ComfoAir-cyclic-reads ComfoAir: Successfully sent packet: 07:f0:00:87:00:34:07:0f -- __init__.py:log_info:527
              2013-11-30 17:47:48,019 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response:  -- __init__.py:log_info:527
              2013-11-30 17:47:48,032 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response: 07:f0:00:86:0b -- __init__.py:log_info:527
              2013-11-30 17:47:48,037 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response: 1f:1e:7b -- __init__.py:log_info:527
              2013-11-30 17:47:48,042 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response: 75:31:00:10:00:00:01:00 -- __init__.py:log_info:527
              2013-11-30 17:47:48,049 INFO     ComfoAir-cyclic-reads ComfoAir: Received chunk of response: ad:07:0f -- __init__.py:log_info:527
              2013-11-30 17:47:48,055 INFO     ComfoAir-cyclic-reads ComfoAir: Successfully received response: 07:f0:00:86:0b:1f:1e:7b:75:31:00:10:00:00:01:00:ad:07:0f -- __init__.py:log_info:527
              2013-11-30 17:47:48,061 DEBUG    ComfoAir-cyclic-reads ComfoAir: Corresponding read command: 00:87:00, decoded data: 1f:1e:7b:75:31:00:10:00:00:01:00 (raw: 1f:1e:7b:75:31:00:10:00:00:01:00) -- __init__.py:log_debug:523
              2013-11-30 17:47:48,066 DEBUG    ComfoAir-cyclic-reads ComfoAir: Matched command ReadExtractAirRPM and read transformed value 117 (raw value was 117) from byte position 4 and byte length 1. -- __init__.py:log_debug:523
              2013-11-30 17:47:48,071 DEBUG    ComfoAir-cyclic-reads ComfoAir: Matched command ReadExtractAirPercentage and read transformed value 30 (raw value was 30) from byte position 2 and byte length 1. -- __init__.py:log_debug:523
              2013-11-30 17:47:48,076 DEBUG    ComfoAir-cyclic-reads ComfoAir: Matched command ReadSupplyAirRPM and read transformed value 123 (raw value was 123) from byte position 3 and byte length 1. -- __init__.py:log_debug:523
              2013-11-30 17:47:48,081 DEBUG    ComfoAir-cyclic-reads ComfoAir: Matched command ReadSupplyAirPercentage and read transformed value 31 (raw value was 31) from byte position 1 and byte length 1. -- __init__.py:log_debug:523
              Sieht das o.k für Dich aus.

              Ich habe eine Comfoair 500 mit vorgeschaltetem Comfofond.
              Leider hat die Comfoairt keinen Temperatursensopr für die abgegebene Luft´. Misst aber beide Eingangstemperaturen vor und nach dem Comfofond. Die Protokollelemente für den Emphaltiesensor können wir rauswerfen.

              Damit sieht die getestete commands.py so aus:
              Code:
              #!/usr/bin/env python
              #########################################################################
              # Copyright 2013 Stefan Kals
              #########################################################################
              #  ComfoAir-Plugin for SmartHome.py.  SmartHome.py ? SmartHome.py 1.0 documentation
              #
              #  This plugin 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 3 of the License, or
              #  (at your option) any later version.
              #
              #  This plugin 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 plugin. If not, see <Licenses - GNU Project - Free Software Foundation>.
              #########################################################################
               
              controlset = {
                  'comfoair350': {
                      'PacketStart': 0x07F0,
                      'PacketEnd': 0x070F,
                      'Acknowledge': 0x07F3,
                      'SpecialCharacter': 0x07,
                      'ResponseCommandIncrement': 1
                  
                  },
                  
                  
                  'comfoair500': {
                      'PacketStart': 0x07F0,
                      'PacketEnd': 0x070F,
                      'Acknowledge': 0x07F3,
                      'SpecialCharacter': 0x07,
                      'ResponseCommandIncrement': -1
                  },
                  
                      
                  'comfoair500_comfofond': {
                      'PacketStart': 0x07F0,
                      'PacketEnd': 0x070F,
                      'Acknowledge': 0x07F3,
                      'SpecialCharacter': 0x07,
                      'ResponseCommandIncrement': -1
                  },
                                        
                    
              }
                  
              # Mandatory command properties: Command, Type, ValueBytes
              # Optional command properties: ResponsePosition (only for Type = Read), ValueTransform
              # Remarks:
              # Command must contain the command code (2 bytes) and the data length (1 byte) and can be optionally followed by data bytes.
              # If ValueBytes is greater than 0, the value of the assigned item is taken, formatted to the number of bytes and added to the telegram.
              # The data length byte must already have the correct amount of data bytes (sum of data bytes provided by 'Command' and dynamic data bytes (of 'ValueBytes' length)).
              # Read-Commands MUST always have a length of 3 bytes and no data (third command byte = 00)
              commandset = {
                  'comfoair350': {
                      'ReadComfortTemperature':       { 'Command': 0x00D100, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 1, 'ValueBytes': 1, 'ValueTransform': 'Temperature' },
                      'ReadFreshAirTemperature':      { 'Command': 0x00D100, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 2, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Frischluft, außen
                      'ReadSupplyAirTemperature':     { 'Command': 0x00D100, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 3, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Zuluft, innen
                      'ReadExtractAirTemperature':    { 'Command': 0x00D100, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 4, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Abluft, innen
                      'ReadExhaustAirTemperature':    { 'Command': 0x00D100, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 5, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Fortluft, außen
                      'ReadGroundHeatTemperature':    { 'Command': 0x00D100, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 7, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Erdwärmetauscher
                      'ReadPreHeatingTemperature':    { 'Command': 0x00D100, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 8, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Vorheizung
                      'ReadSupplyAirPercentage':      { 'Command': 0x000B00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 1, 'ValueBytes': 1 },
                      'ReadExtractAirPercentage':     { 'Command': 0x000B00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 2, 'ValueBytes': 1 },
                      'ReadSupplyAirRPM':             { 'Command': 0x000B00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 3, 'ValueBytes': 2, 'ValueTransform': 'RPM' },
                      'ReadExtractAirRPM':            { 'Command': 0x000B00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 5, 'ValueBytes': 2, 'ValueTransform': 'RPM' },
                      'ReadBypassPercentage':         { 'Command': 0x000D00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 1, 'ValueBytes': 1 },
                      'ReadPreHeatingStatus':         { 'Command': 0x000D00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 2, 'ValueBytes': 1 },
                      'ReadOperatingHoursAway':       { 'Command': 0x00DD00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 1, 'ValueBytes': 3 },
                      'ReadOperatingHoursLow':        { 'Command': 0x00DD00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 4, 'ValueBytes': 3 },
                      'ReadOperatingHoursMedium':     { 'Command': 0x00DD00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 7, 'ValueBytes': 3 },
                      'ReadOperatingHoursAntiFreeze': { 'Command': 0x00DD00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 10, 'ValueBytes': 2 },
                      'ReadOperatingHoursPreHeating': { 'Command': 0x00DD00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 12, 'ValueBytes': 2 },
                      'ReadOperatingHoursBypass':     { 'Command': 0x00DD00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 14, 'ValueBytes': 2 },
                      'ReadOperatingHoursFilter':     { 'Command': 0x00DD00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 16, 'ValueBytes': 2 },
                      'ReadOperatingHoursHigh':       { 'Command': 0x00DD00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 18, 'ValueBytes': 3 },
                      'ReadCurrentVentilationLevel':  { 'Command': 0x00CD00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 9, 'ValueBytes': 1 },
                      'WriteComfortTemperature':      { 'Command': 0x00D301, 'CommandBytes': 3, 'Type': 'Write', 'ValueBytes': 1, 'ValueTransform': 'Temperature' },
                      'WriteVentilationLevel':        { 'Command': 0x009901, 'CommandBytes': 3, 'Type': 'Write', 'ValueBytes': 1 },
                      'WriteVentilationLevelAway':    { 'Command': 0x00990101, 'CommandBytes': 4, 'Type': 'Write', 'ValueBytes': 0 },
                      'WriteVentilationLevelLow':     { 'Command': 0x00990102, 'CommandBytes': 4, 'Type': 'Write', 'ValueBytes': 0 },
                      'WriteVentilationLevelMedium':  { 'Command': 0x00990103, 'CommandBytes': 4, 'Type': 'Write', 'ValueBytes': 0 },
                      'WriteVentilationLevelHigh':    { 'Command': 0x00990104, 'CommandBytes': 4, 'Type': 'Write', 'ValueBytes': 0 },
                      'WriteFilterReset':             { 'Command': 0x00DB0400000001, 'CommandBytes': 7, 'Type': 'Write', 'ValueBytes': 0 },
                      'WriteErrorReset':              { 'Command': 0x00DB0401000000, 'CommandBytes': 7, 'Type': 'Write', 'ValueBytes': 0 }
                  },
                  'comfoair500': {
                      'ReadComfortTemperature':       { 'Command': 0x008B00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 2, 'ValueBytes': 1, 'ValueTransform': 'Temperature' },
                      'ReadFreshAirTemperature':      { 'Command': 0x008500, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 4, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Frischluft, außen
                      'ReadExtractAirTemperature':    { 'Command': 0x008500, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 5, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Abluft, innen
                      'ReadExhaustAirTemperature':    { 'Command': 0x008500, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 6, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Fortluft, außen
                      # comfoair 500 has no Sensor for Supply Air - External Sensor ( e.g. Onewire ) required for full calculation
                      'ReadSupplyAirPercentage':      { 'Command': 0x008700, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 1, 'ValueBytes': 1 },
                      'ReadExtractAirPercentage':     { 'Command': 0x008700, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 2, 'ValueBytes': 1 },
                      'ReadSupplyAirRPM':             { 'Command': 0x008700, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 3, 'ValueBytes': 1 },
                      'ReadExtractAirRPM':            { 'Command': 0x008700, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 4, 'ValueBytes': 1 },
                      #'ReadBypassPercentage':         { 'Command': 0x008500, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 1, 'ValueBytes': 1 },  # remove if not supported by your device
                      #'ReadEnthalpyPercentage':       { 'Command': 0x00C100, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 1, 'ValueBytes': 1 },  # remove if not supported by your device
                      'ReadEnthalpyTemperature':      { 'Command': 0x00C100, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 2, 'ValueBytes': 1, 'ValueTransform': 'Temperature' },
                      'WriteVentilationLevel':        { 'Command': 0x00A001, 'CommandBytes': 3, 'Type': 'Write', 'ValueBytes': 1 }
               
                  },
                  'comfoair500_comfofond': {
                      'ReadComfortTemperature':       { 'Command': 0x008B00, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 2, 'ValueBytes': 1, 'ValueTransform': 'Temperature' },
                      'ReadFreshAirTemperature':      { 'Command': 0x008500, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 4, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Frischluft, von Comfofond
                      'ReadIntakeAirTemperature':     { 'Command': 0x008500, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 7, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Ansaugluft vor Comfofond
                      'ReadExtractAirTemperature':    { 'Command': 0x008500, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 5, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Abluft, innen
                      'ReadExhaustAirTemperature':    { 'Command': 0x008500, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 6, 'ValueBytes': 1, 'ValueTransform': 'Temperature' }, # Fortluft, außen
                      # comfoair 500 has no Sensor for Supply Air - External Sensor ( e.g. Onewire ) required for full calculation
                      'ReadSupplyAirPercentage':      { 'Command': 0x008700, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 1, 'ValueBytes': 1 },
                      'ReadExtractAirPercentage':     { 'Command': 0x008700, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 2, 'ValueBytes': 1 },
                      'ReadSupplyAirRPM':             { 'Command': 0x008700, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 3, 'ValueBytes': 1 },
                      'ReadExtractAirRPM':            { 'Command': 0x008700, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 4, 'ValueBytes': 1 },
                      'ReadBypassPercentage':         { 'Command': 0x008500, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 1, 'ValueBytes': 1 }, 
                      #'ReadEnthalpyPercentage':       { 'Command': 0x00C100, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 1, 'ValueBytes': 1 }, 
                      #'ReadEnthalpyTemperature':      { 'Command': 0x00C100, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 2, 'ValueBytes': 1, 'ValueTransform': 'Temperature' },
                      'WriteVentilationLevel':        { 'Command': 0x00A001, 'CommandBytes': 3, 'Type': 'Write', 'ValueBytes': 1 }
                  }
              }
              und der plugin.conf Eintrag so:

              Code:
              [comfoair]
                  class_name = ComfoAir
                  class_path = plugins.comfoair
                  kwltype = comfoair500_comfofond       # Currently supported: comfoair350 and comfoair500 / comfoair500_comfofond
                  host = 192.168.123.118       # Provide host and port if you want to use TCP connection (for a TCP to serial converter)
                  port = 5555                 # Port
                  #serialport = /dev/ttyUSB0  # Enable this if you want to use a serial connection
              und zur Vollständigkeit noch meine items:

              Code:
              [kwl]        
                    [[temp]]
                      [[[comfort]]]
                          type = num
                          comfoair_read = ReadComfortTemperature
                          comfoair_read_cycle = 60 # seconds
                          comfoair_init = true
                      [[[freshair]]]
                          type = num
                          comfoair_read = ReadFreshAirTemperature
                          comfoair_read_cycle = 60 # seconds
                          comfoair_init = true
                          sqlite = yes
                      [[[intakeair]]]
                          type = num
                          comfoair_read = ReadIntakeAirTemperature
                          comfoair_read_cycle = 60 # seconds
                          comfoair_init = true
                          sqlite = yes
                      [[[extractair]]]
                          type = num
                          comfoair_read = ReadExtractAirTemperature
                          comfoair_read_cycle = 60 # seconds
                          comfoair_init = true
                          sqlite = yes
                      [[[exhaustair]]]
                          type = num
                          comfoair_read = ReadExhaustAirTemperature
                          comfoair_read_cycle = 60 # seconds
                          comfoair_init = true
                          sqlite = yes
                  
                  [[extractair]]
                      [[[rpm]]]
                          type = num
                          comfoair_read = ReadExtractAirRPM
                          comfoair_read_cycle = 60 # seconds
                          comfoair_init = true
                      [[[level]]]
                          type = num
                          comfoair_read = ReadExtractAirPercentage
                          comfoair_read_cycle = 60 # seconds
                          comfoair_init = true
                  
                  [[supplyair]]
                      [[[rpm]]]
                          type = num
                          comfoair_read = ReadSupplyAirRPM
                          comfoair_read_cycle = 60 # seconds
                          comfoair_init = true
                      [[[level]]]
                          type = num
                          comfoair_read = ReadSupplyAirPercentage
                          comfoair_read_cycle = 60 # seconds
                          comfoair_init = true
                        
                  [[bypass]]
                      type = num
                      comfoair_read = ReadBypassPercentage
                      comfoair_read_cycle = 60 # seconds
                      comfoair_init = true     
                       
                  
                 
                    
                          
                          
                          
                  
                  [[heatpreparationratio]]
                      type = num
                      eval = (sh.ow.supplyair() - sh.kwl.temp.freshair()) / (sh.kwl.temp.extractair() - sh.kwl.temp.exhaustair()) * 100
                      eval_trigger = sh.ow.supplyair | kwl.temp.freshair | kwl.temp.extractair | kwl.temp.exhaustair
                   [[heatpreparationratio_total]]
                      type = num
                      eval = (sh.ow.supplyair() - sh.kwl.temp.intakeair()) / (sh.kwl.temp.extractair() - sh.kwl.temp.exhaustair()) * 100
                      eval_trigger = sh.owsupplyair | kwl.temp.intakeair | kwl.temp.extractair | kwl.temp.exhaustair
              Gruß Stephan

              Kommentar


                #37
                Zitat von shs2 Beitrag anzeigen
                ich habe heute die direkte USB Verbindung abgeklemmt und einen alten Notebook als Server betrieben. Mit gleicher Hardware V.24 und RS485 habe ich keine Probleme mehr, dass das Plugin aus dem Tritt gerät.
                Hi Stephan,

                super, dass du die Probleme beseitigt hast!
                Bei den beiden RPM Werten fehlt noch eine Transformation, ich glaube nur, dass sie anders als bei der 350 zu berechnen ist (bei der ComfoAir 350 gibts 2 Bytes Values, bei dir nur 1 Byte). Du kannst beim Command mal ValueTransform: RPM probieren, wird aber zu 99% nicht passen.

                Ist das "custom", auf welcher Byte Position deine zusätzliche Intake Temperatur aufscheint oder wäre das bei jeder Installation mit ComfoFond so? Ich würde hald gerne nur eine Command-Config für ComfoAir500 haben, da das Protokoll ja prinzipiell gleich ist. Würde vorschlagen, dass man einfach alle Commands auflistet, die theoretisch möglich sind und Leute ohne ComfoFond benutzen dann hald manche nicht.

                Das Log von der Kommunikation schaut gut aus!

                LG Stefan

                Kommentar


                  #38
                  Hallo Stefan,

                  Ich denke du kannst den von mir angelegten Parametersatz für die 500_comfofond als ("Gold") Standard nehmen.
                  Bei mir wurde nichts kundenspezifisch gemacht.
                  Offenbar wird hier nur ein weiterer Temperatursensoreingang belegt - der aber nur in der Comfofond Anleitung, nicht aber in der 500 dokumentiert ist.
                  Es gibt wohl 3 Varianten der Comfoair

                  B
                  BE - Erweiterte Steuerungsmöglichkeiten ( z.B f .Comfofond)
                  BFB - F mit Fernbedienung


                  Ich denke der Enthalpiesensor ist nur ( wenn überhaupt- in den Unterlagen konnte ich keinen Hinweis finden) bei der 500 BFB verbaut. Für meine 500 BE hab ich dies wg. Fehlermeldungen entfernt.

                  Wenn dies http://matsab.de/index.php/de/comfoair
                  hier stimmt, hat aber die 500BFB diesen Sensor:


                  Interessant wäre rauszufinden, ob Störung, Filterwechsel und Ansteuerung Comfofond auslesbar sind. Evt. versteckt sich dies ja bereits in den unkommentierten Protokollelementen der bekannten Aufrufe.
                  Beim nächsten Filterwechsel versuche ich hierzu mal etwas rauszubekommen.

                  Gruß Stephan

                  Kommentar


                    #39
                    einen neuen PArameter hab ich noch

                    Code:
                     'ReadEwtPercentage':            { 'Command': 0x008700, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 5, 'ValueBytes': 1 },
                    Wobei 49 EWT Pumpe "ein" repräsentiert - und 17 EWT aus.
                    Frag nicht warum diese beiden Werte (Bit 5 und nicht Bit 5)


                    Gru0ß Stephan

                    Kommentar


                      #40
                      @shs2
                      Hallo Stephan,

                      wie hast Du die Kommunikation zu Deiner KWL über RS485 endgültig erfolgreich gelöst?
                      Was hast Du für einen Schnittstellenadapter bzw. hast Du es jetzt über IP Adapter gelöst?
                      ich habe heute die direkte USB Verbindung abgeklemmt und einen alten Notebook als Server betrieben. Mit gleicher Hardware V.24 und RS485 habe ich keine Probleme mehr, dass das Plugin aus dem Tritt gerät.
                      Ich werde meinen Zugang auf IP umstellen und gut ist (so hoffe ich).

                      Kommentar


                        #41
                        Noch läuft bei mir die Übergangslösung mir RS485 adabter am Notebook (sehr stabil) . Meine Lieferung aus China ( RS485 - IP) Board aus der Bucht ist leider noch nicht da.
                        Berichte hier wenn das Board da ist und funktioniert.

                        Gruß Stephan

                        Kommentar


                          #42
                          Neue Version

                          Hallo allerseits!

                          Danke shs2 und ohinckel fürs Melden eines Bugs: Das Plugin hatte noch einen schlimmen Fehler, nämlich dass das Initialisieren statt nur einmal alle 10 Minuten passierte und dabei jedes Mal einen neuen Thread erzeugte (bis es keine mehr gab). *ups*

                          Ist jetzt behoben, sollte nicht mehr passieren. Hab im GIT einen Pull Request gemacht, kann aber noch ein Zeiterl dauern, bis die neue Version im Develop Branch auftaucht.

                          Bis dahin könnt ihr mal den Code selber tauschen:

                          Code:
                          #!/usr/bin/env python
                          #########################################################################
                          # Copyright 2013 Stefan Kals
                          #########################################################################
                          #  ComfoAir-Plugin for SmartHome.py.  http://mknx.github.com/smarthome/
                          #
                          #  This plugin 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 3 of the License, or
                          #  (at your option) any later version.
                          #
                          #  This plugin 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 plugin. If not, see <http://www.gnu.org/licenses/>.
                          #########################################################################
                          
                          import logging
                          import socket
                          import time
                          import serial
                          import re
                          import threading
                          from . import commands
                          
                          logger = logging.getLogger('ComfoAir')
                          
                          class ComfoAir():
                          
                              def __init__(self, smarthome, host=None, port=0, serialport=None, kwltype='comfoair350'):
                                  self.connected = False
                                  self._sh = smarthome
                                  self._params = {}
                                  self._init_cmds = []
                                  self._cyclic_cmds = {}
                                  self._lock = threading.Lock()
                                  self._host = host
                                  self._port = int(port)
                                  self._serialport = serialport
                                  self._connection_attempts = 0
                                  self._connection_errorlog = 60
                                  self._initread = False
                                  smarthome.connections.monitor(self)
                          
                                  # Load controlset and commandset
                                  if kwltype in commands.controlset and kwltype in commands.commandset:
                                      self._controlset = commands.controlset[kwltype]
                                      self._commandset = commands.commandset[kwltype]
                                      self.log_info('Loaded commands for KWL type \'{}\''.format(kwltype))
                                  else:
                                      self.log_err('Commands for KWL type \'{}\' could not be found!'.format(kwltype))
                                      return None
                          
                                  # Remember packet config
                                  self._packetstart = self.int2bytes(self._controlset['PacketStart'], 2)
                                  self._packetend = self.int2bytes(self._controlset['PacketEnd'], 2)
                                  self._acknowledge = self.int2bytes(self._controlset['Acknowledge'], 2)
                                  self._specialchar = self.int2bytes(self._controlset['SpecialCharacter'], 1)
                                  self._reponsecommandinc = self._controlset['ResponseCommandIncrement']
                                  self._commandlength = 2
                                  self._checksumlength = 1
                                  
                              def connect(self):
                                  if self._serialport is not None:
                                      self.connect_serial()
                                  else:
                                      self.connect_tcp()
                                  
                              def connect_tcp(self):
                                  self._lock.acquire()
                                  try:
                                      self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                                      self._sock.settimeout(2)
                                      self._sock.connect((self._host, self._port))
                                  except Exception as e:
                                      self._connection_attempts -= 1
                                      if self._connection_attempts <= 0:
                                          self.log_err('could not connect to {}:{}: {}'.format(self._host, self._port, e))
                                          self._connection_attempts = self._connection_errorlog
                                      self._lock.release()
                                      return
                                  else:
                                      self.connected = True
                                      self.log_info('connected to {}:{}'.format(self._host, self._port))
                                      self._connection_attempts = 0
                                      self._lock.release()
                              
                              def connect_serial(self):
                                  self._lock.acquire()
                                  try:
                                      self._serialconnection = serial.Serial(
                                              self._serialport, 9600, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_ONE, timeout=2)
                                  except Exception as e:
                                      self._connection_attempts -= 1
                                      if self._connection_attempts <= 0:
                                          self.log_err('could not connect to {}: {}'.format(self._serialport, e))
                                          self._connection_attempts = self._connection_errorlog
                                      self._lock.release()
                                      return
                                  else:
                                      self.connected = True
                                      self.log_info('connected to {}'.format(self._serialport))
                                      self._connection_attempts = 0
                                      self._lock.release()
                          
                              def disconnect(self):
                                  if self._serialport is not None:
                                      self.disconnect_serial()
                                  else:
                                      self.disconnect_tcp()
                                  
                              def disconnect_tcp(self): 
                                  self.connected = False
                                  try:
                                      self._sock.shutdown(socket.SHUT_RDWR)
                                  except:
                                      pass
                                  try:
                                      self._sock.close()
                                  except:
                                      pass
                          
                              def disconnect_serial(self): 
                                  self.connected = False
                                  try:
                                      self._serialconnection.close()
                                      self._serialconnection = None
                                  except:
                                      pass
                                  
                              def send_bytes(self, packet):
                                  if self._serialport is not None:
                                      self.send_bytes_serial(packet)
                                  else:
                                      self.send_bytes_tcp(packet)
                                  
                              def send_bytes_tcp(self, packet):
                                  self._sock.sendall(packet)
                          
                              def send_bytes_serial(self, packet):
                                  self._serialconnection.write(packet)
                                  
                              def read_bytes(self, length):
                                  if self._serialport is not None:
                                      return self.read_bytes_serial(length)
                                  else:
                                      return self.read_bytes_tcp(length)
                                  
                              def read_bytes_tcp(self, length):
                                  return self._sock.recv(length)
                          
                              def read_bytes_serial(self, length):
                                  return self._serialconnection.read(length)
                           
                              def parse_item(self, item):
                                  # Process the read config
                                  if 'comfoair_read' in item.conf:
                                      commandname = item.conf['comfoair_read']
                                      if (commandname == None or commandname not in self._commandset):
                                          self.log_err('Item {} contains invalid read command \'{}\'!'.format(item, commandname))
                                          return None
                                      
                                      # Remember the read config to later update this item if the configured response comes in
                                      self.log_info('Item {} reads by using command \'{}\'.'.format(item, commandname))
                                      commandconf = self._commandset[commandname]
                                      commandcode = commandconf['Command']
                          
                                      if not commandcode in self._params:
                                          self._params[commandcode] = {'commandname': [commandname], 'items': [item]}
                                      elif not item in self._params[commandcode]['items']:
                                          self._params[commandcode]['commandname'].append(commandname)
                                          self._params[commandcode]['items'].append(item)
                          
                                      # Allow items to be automatically initiated on startup
                                      if ('comfoair_init' in item.conf and item.conf['comfoair_init'] == 'true'):
                                          self.log_info('Item {} is initialized on startup.'.format(item))
                                          # Only add the item to the initial commands if it is not cyclic. Cyclic commands get called on init because this is the first cycle...
                                          if not commandcode in self._init_cmds and 'comfoair_read_cycle' not in item.conf:
                                              self._init_cmds.append(commandcode)
                          
                                      # Allow items to be cyclically updated
                                      if ('comfoair_read_cycle' in item.conf):
                                          cycle = int(item.conf['comfoair_read_cycle'])
                                          self.log_info('Item {} should read cyclic every {} seconds.'.format(item, cycle))
                          
                                          if not commandcode in self._cyclic_cmds:
                                              self._cyclic_cmds[commandcode] = {'cycle': cycle, 'nexttime': 0}
                                          else:
                                              # If another item requested this command already with a longer cycle, use the shorter cycle now
                                              if self._cyclic_cmds[commandcode]['cycle'] > cycle:
                                                  self._cyclic_cmds[commandcode]['cycle'] = cycle
                          
                                  # Process the send config
                                  if 'comfoair_send' in item.conf:
                                      commandname = item.conf['comfoair_send']
                                      if commandname == None:
                                          return None
                                      elif commandname not in self._commandset:
                                          self.log_err('Item {} contains invalid write command \'{}\'!'.format(item, commandname))
                                          return None
                                      
                                      self.log_info('Item {} writes by using command \'{}\''.format(item, commandname))
                                      return self.update_item
                                  else:
                                      return None
                          
                              def parse_logic(self, logic):
                                  pass
                          
                              def update_item(self, item, caller=None, source=None, dest=None):
                                  if caller != 'ComfoAir' and 'comfoair_send' in item.conf:
                                      commandname = item.conf['comfoair_send']
                          
                                      if type(item) != int:
                                          value = int(item())
                                      else:
                                          value = item()
                          
                                      # Send write command
                                      self.send_command(commandname, value)
                          
                                      # If a read command should be sent after write
                                      if 'comfoair_read' in item.conf and 'comfoair_read_afterwrite' in item.conf:
                                          readcommandname = item.conf['comfoair_read']
                                          readafterwrite = item.conf['comfoair_read_afterwrite']
                                          self.log_info('Attempting read after write for item {}, command {}, delay {}'.format(item, readcommandname, readafterwrite))
                                          if readcommandname is not None and readafterwrite is not None:
                                              aw = float(readafterwrite)
                                              time.sleep(aw)
                                              self.send_command(readcommandname)
                                      
                                      # If commands should be triggered after this write        
                                      if 'comfoair_trigger' in item.conf:
                                          trigger = item.conf['comfoair_trigger']
                                          if trigger == None:
                                              self.log_err('Item {} contains invalid trigger command list \'{}\'!'.format(item, trigger))
                                          else:
                                              tdelay = 5 # default delay
                                              if 'comfoair_trigger_afterwrite' in item.conf:
                                                  tdelay = float(item.conf['comfoair_trigger_afterwrite'])
                                              if type(trigger) != list:
                                                  trigger = [trigger] 
                                              for triggername in trigger:
                                                  triggername = triggername.strip()
                                                  if triggername is not None and readafterwrite is not None:
                                                      self.log_info('Triggering command {} after write for item {}'.format(triggername, item))
                                                      time.sleep(tdelay)
                                                      self.send_command(triggername)
                          
                              def handle_cyclic_cmds(self):
                                  # Read all cyclic commands
                                  currenttime = time.time()
                                  for commandcode in list(self._cyclic_cmds.keys()):
                                      entry = self._cyclic_cmds[commandcode]
                                      # Is the command already due?
                                      if entry['nexttime'] <= currenttime:
                                          commandname = self.commandname_by_commandcode(commandcode)
                                          self.log_info('Triggering cyclic read command: {}'.format(commandname))
                                          self.send_command(commandname)
                                          entry['nexttime'] = currenttime + entry['cycle']
                                  
                              def send_command(self, commandname, value=None):
                                  try:
                                      #self.log_debug('Got a new send job: Command {} with value {}'.format(commandname, value))
                                      
                                      # Get command config
                                      commandconf = self._commandset[commandname]
                                      commandcode = int(commandconf['Command'])
                                      commandcodebytecount = commandconf['CommandBytes']
                                      commandtype = commandconf['Type']
                                      commandvaluebytes = commandconf['ValueBytes']
                                      #self.log_debug('Command config: {}'.format(commandconf))
                                      
                                      # Transform value for write commands
                                      #self.log_debug('Got value: {}'.format(value))
                                      if 'ValueTransform' in commandconf and value is not None and value != '' and commandtype == 'Write':
                                          commandtransform = commandconf['ValueTransform']
                                          value = self.value_transform(value, commandtype, commandtransform)
                                          #self.log_debug('Transformed value using method {} to {}'.format(commandtransform, value))
                              
                                      # Build value byte array
                                      valuebytes = bytearray()
                                      if value is not None and commandvaluebytes > 0:
                                          valuebytes = self.int2bytes(value, commandvaluebytes)
                                      #self.log_debug('Created value bytes: {}'.format(valuebytes))
                              
                                      # Calculate the checksum
                                      commandbytes = self.int2bytes(commandcode, commandcodebytecount)
                                      payload = bytearray()
                                      payload.extend(commandbytes)
                                      if len(valuebytes) > 0:
                                          payload.extend(valuebytes)
                                      checksum = self.calc_checksum(payload)
                              
                                      # Build packet
                                      packet = bytearray()
                                      packet.extend(self.int2bytes(self._controlset['PacketStart'], 2))
                                      packet.extend(commandbytes)
                                      if len(valuebytes) > 0:
                                          packet.extend(self.encode_specialchars(valuebytes))
                                      packet.extend(self.int2bytes(checksum, 1))
                                      packet.extend(self.int2bytes(self._controlset['PacketEnd'], 2))
                                      self.log_info('Preparing command {} with value {} (transformed to value byte \'{}\') to be sent.'.format(commandname, value, self.bytes2hexstring(valuebytes)))
                                      
                                      # Use a lock to allow only one sender at a time
                                      self._lock.acquire()
                          
                                      if not self.connected:
                                          raise Exception("No connection to ComfoAir.")
                                      
                                      try:
                                          self.send_bytes(packet)
                                          self.log_info('Successfully sent packet: {}'.format(self.bytes2hexstring(packet)))
                                      except Exception as e:
                                          raise Exception('Exception while sending: {}'.format(e))
                                      
                                      if commandtype == 'Read':
                                          packet = bytearray()
                                          
                                          # Try to receive a packet start, a command and a data length byte
                                          firstpartlen = len(self._packetstart) + self._commandlength + 1
                                          while self.alive and len(packet) < firstpartlen:
                                              try:
                                                  bytestoreceive = firstpartlen - len(packet)
                                                  self.log_debug('Trying to receive {} bytes for the first part of the response.'.format(bytestoreceive))
                                                  chunk = self.read_bytes(bytestoreceive)
                                                  self.log_info('Received chunk of response: {}'.format(self.bytes2hexstring(chunk)))
                                                  
                                                  # Cut away old ACK (but only if the telegram wasn't started already)
                                                  if len(packet) == 0:
                                                      chunk = self.remove_ack_begin(chunk)
                                                  packet.extend(chunk)
                                              except socket.timeout:
                                                  raise Exception("error receiving first part of packet: timeout")
                                              except Exception as e:
                                                  raise Exception("error receiving first part of packet: {}".format(e))
                              
                                          datalen = packet[firstpartlen - 1]
                                          #self.log_info('Got a data length of: {}'.format(datalen))
                                          packetlen = firstpartlen + datalen + self._checksumlength + len(self._packetend)
                              
                                          # Try to receive the second part of the packet
                                          while self.alive and len(packet) < packetlen or packet[-2:] != self._packetend:
                                              try:
                                                  # In case of doubled special characters, the packet can be longer (try one byte more at a time)
                                                  if len(packet) >= packetlen and packet[-2:] != self._packetend:
                                                      packetlen = len(packet) + 1
                                                      self.log_info('Extended packet length because of encoded characters.'.format(self.bytes2hexstring(chunk)))
                                                  
                                                  # Receive next chunk
                                                  bytestoreceive = packetlen - len(packet)
                                                  self.log_debug('Trying to receive {} bytes for the second part of the response.'.format(bytestoreceive))
                                                  chunk = self.read_bytes(bytestoreceive)
                                                  self.log_info('Received chunk of response: {}'.format(self.bytes2hexstring(chunk)))
                                                  packet.extend(chunk)
                                              except socket.timeout:
                                                  raise Exception("error receiving second part of packet: timeout")
                                              except Exception as e:
                                                  raise Exception("error receiving second part of packet: {}".format(e))
                              
                                          # Send ACK
                                          self.send_bytes(self._acknowledge)
                                          
                                          # Parse response
                                          self.parse_response(packet)
                                  
                                  except Exception as e:
                                      self.disconnect()
                                      self.log_err("send_command failed: {}".format(e))
                          
                                  finally:            
                                      # At the end, release the lock
                                      self._lock.release()
                          
                              def parse_response(self, response):
                                  #resph = self.bytes2int(response)
                                  self.log_info('Successfully received response: {}'.format(self.bytes2hexstring(response)))
                          
                                  # A telegram looks like this: start sequence (2 bytes), command (2 bytes), data length (1 byte), data, checksum (1 byte), end sequence (2 bytes, already cut away)
                                  commandcodebytes = response[2:4]
                                  commandcodebytes[1] -= self._reponsecommandinc # The request command of this response is -1 (for comfoair 350)
                                  commandcodebytes.append(0) # Add a data length byte of 0 (always true for read commands)
                                  commandcode = self.bytes2int(commandcodebytes)
                          
                                  # Remove begin and checksum to get the data
                                  rawdatabytes = response[5:-3]
                          
                                  # Decode special characters
                                  databytes = self.decode_specialchars(rawdatabytes)
                                  self.log_debug('Corresponding read command: {}, decoded data: {} (raw: {})'.format(self.bytes2hexstring(commandcodebytes), self.bytes2hexstring(databytes), self.bytes2hexstring(rawdatabytes)))
                          
                                  # Validate checksum
                                  packetpart = bytearray()
                                  packetpart.extend(response[2:5]) # Command and data length
                                  packetpart.extend(databytes) # Decoded data bytes
                                  checksum = self.calc_checksum(packetpart)
                                  receivedchecksum = response[len(response) - len(self._packetend) - 1]
                                  if (receivedchecksum != checksum):
                                      self.log_err('Calculated checksum of {} does not match received checksum of {}! Ignoring reponse.'.format(checksum, receivedchecksum))
                                      return
                          
                                  # Find items using this response command
                                  if commandcode in self._params.keys():
                                      # Iterate over all corresponding items
                                      for i in range(0, len(self._params[commandcode]['items'])):
                                          item = self._params[commandcode]['items'][i]
                                          commandname = self._params[commandcode]['commandname'][i]
                          
                                          # Get command config
                                          commandconf = self._commandset[commandname]
                                          commandtype = commandconf['Type']
                                          commandvaluebytes = commandconf['ValueBytes']
                                          commandresppos = 0
                                          if 'ResponsePosition' in commandconf:
                                              commandresppos = commandconf['ResponsePosition']
                                          commandtransform = ''
                                          if 'ValueTransform' in commandconf:
                                              commandtransform = commandconf['ValueTransform']
                          
                                          # Is there enough data for the configured position?
                                          index = commandresppos - 1
                                          if index + commandvaluebytes <= len(databytes):
                                              # Extract value
                                              valuebytes = databytes[index:index + commandvaluebytes]
                                              rawvalue = self.bytes2int(valuebytes)
                                          
                                              # Tranform value
                                              value = self.value_transform(rawvalue, commandtype, commandtransform)
                                              self.log_debug('Matched command {} and read transformed value {} (raw value was {}) from byte position {} and byte length {}.'.format(commandname, value, rawvalue, commandresppos, commandvaluebytes))
                          
                                              # Update item
                                              item(value, 'ComfoAir')
                                          else:
                                              self.log_err('Telegram did not contain enough data bytes for the configured command {} to extract a value!'.format(commandname))
                          
                              def run(self):
                                  self.alive = True
                                  self._sh.scheduler.add('ComfoAir-init', self.send_init_commands, prio=5, cycle=600, offset=2)
                                  maxloops = 20
                                  loops = 0 
                                  while self.alive and not self._initread and loops < maxloops:  # wait for init read to finish
                                      time.sleep(0.5)
                                      loops += 1
                                  self._sh.scheduler.remove('ComfoAir-init')
                                          
                              def stop(self):
                                  self._sh.scheduler.remove('ComfoAir-cyclic')
                                  self.alive = False
                                  self.disconnect()
                                 
                              def send_init_commands(self):
                                  try:
                                      # Do the init read commands
                                      if self._init_cmds != []:
                                          if self.connected:
                                              self.log_info('Starting initial read commands.')
                                              for commandcode in self._init_cmds:
                                                  commandname = self.commandname_by_commandcode(commandcode)
                                                  self.send_command(commandname)
                              
                                      # Find the shortest cycle
                                      shortestcycle = -1
                                      for commandname in list(self._cyclic_cmds.keys()):
                                          entry = self._cyclic_cmds[commandname]
                                          if shortestcycle == -1 or entry['cycle'] < shortestcycle:
                                              shortestcycle = entry['cycle']
                              
                                      # Start the worker thread
                                      if shortestcycle != -1:
                                          # Balance unnecessary calls and precision
                                          workercycle = int(shortestcycle / 2)
                                          self._sh.scheduler.add('ComfoAir-cyclic', self.handle_cyclic_cmds, cycle=workercycle, prio=5, offset=0)
                                          self.log_info('Added cyclic worker thread ({} sec cycle). Shortest item update cycle found: {} sec.'.format(workercycle, shortestcycle))
                                  finally:
                                      self._initread = True
                          
                              def remove_ack_begin(self, packet):
                                  # Cut old ACK responses from ComfoAir before the real message
                                  acklen = len(self._acknowledge)
                                  while len(packet) >= acklen and packet[0:acklen] == self._acknowledge:
                                      packet = packet[acklen:]
                                  return packet
                              
                              def calc_checksum(self, packetpart):
                                  return (sum(packetpart) + 173) % 256
                              
                              def log_debug(self, text):    
                                  logger.debug('ComfoAir: {}'.format(text))    
                          
                              def log_info(self, text):    
                                  logger.info('ComfoAir: {}'.format(text))    
                          
                              def log_err(self, text):    
                                  logger.error('ComfoAir: {}'.format(text))    
                              
                              def int2bytes(self, value, length):
                                  # Limit value to the passed byte length
                                  value = value % (2 ** (length * 8))
                                  return value.to_bytes(length, byteorder='big')
                              
                              def bytes2int(self, bytesvalue):
                                  return int.from_bytes(bytesvalue, byteorder='big', signed=False)
                              
                              def bytes2hexstring(self, bytesvalue):
                                  return ":".join("{:02x}".format(c) for c in bytesvalue)
                                          
                              def encode_specialchars(self, packet):
                                  specialchar = self._controlset['SpecialCharacter']
                                  encodedpacket = bytearray()
                                  for count in range(len(packet)):
                                      char = packet[count]
                                      encodedpacket.append(char)
                                      if char == specialchar:
                                          # Encoding works by doubling the special char
                                          self.log_debug('Encoded special char at position {} of data bytes {}.'.format(count, self.bytes2hexstring(packet)))
                                          encodedpacket.append(char)
                                  #self.log_debug('Encoded data bytes: {}.'.format(encodedpacket))
                                  return encodedpacket
                              
                              def decode_specialchars(self, packet):
                                  specialchar = self._controlset['SpecialCharacter']
                                  decodedpacket = bytearray()
                                  prevchar = ''
                                  specialcharremoved = 0
                                  for count in range(len(packet)):
                                      char = packet[count]
                                      if count > 0:
                                          prevchar = packet[count - 1]
                                      if char == specialchar and prevchar == specialchar and specialcharremoved == 0:
                                          # Decoding works by dropping double sepcial chars
                                          self.log_debug('Decoded special char at position {} of packet {}.'.format(count, self.bytes2hexstring(packet)))
                                          specialcharremoved = 1
                                      else:
                                          decodedpacket.append(char)
                                          # Reset dropping marker
                                          specialcharremoved = 0
                                  return decodedpacket
                              
                              def value_transform(self, value, commandtype, transformmethod):
                                  if transformmethod == 'Temperature':
                                      if commandtype == 'Read':
                                          return value / 2 - 20
                                      elif commandtype == 'Write':
                                          return (value + 20) * 2
                                  elif transformmethod == 'RPM':
                                      if commandtype == 'Read':
                                          return int(1875000 / value)
                                      elif commandtype == 'Write':
                                          return int(1875000 / value)
                                  return value
                              
                              def commandname_by_commandcode(self, commandcode):
                                  for commandname in self._commandset.keys():
                                      if self._commandset[commandname]['Command'] == commandcode:
                                          return commandname
                                  return None
                          LG Stefan

                          Kommentar


                            #43
                            Hallo Stefan, läuft stabil.

                            Bist Du noch so nett und checkst den neuen Parameter aus #39 in der




                            Code:
                            'ReadEwtPercentage': { 'Command': 0x008700, 'CommandBytes': 3, 'Type': 'Read', 'ResponsePosition': 5, 'ValueBytes': 1 },
                            Wobei 49 EWT Pumpe "ein" repräsentiert - und 17 EWT aus.
                            Frag nicht warum diese beiden Werte (Bit 5 und nicht Bit 5)
                            Config mit ein ( Status EWT)
                            Danke Dir nochmals

                            Kommentar


                              #44
                              IP Umrüstung erfolgreich abgeschlossen

                              Zitat von Traqso Beitrag anzeigen
                              @shs2
                              Hallo Stephan,

                              wie hast Du die Kommunikation zu Deiner KWL über RS485 endgültig erfolgreich gelöst?
                              Was hast Du für einen Schnittstellenadapter bzw. hast Du es jetzt über IP Adapter gelöst?
                              So vor 2 Wochen ist mein RS485 / RS232 IP Adapter aus China eingetroffen.
                              Jetzt habe ich einen absolut stabilen Betrieb mit dem Plugin.

                              Die kleine Platine selbst habe ich innerhalb der KWL eingebaut (auf einer Kunststoffverlängerung hinter dem Displaymodul) . Stromversorgung über eigenes Netzteil , da ich die 5V der ComfoAir nicht zusätzlich belasten wollte

                              Bezugsquelle:
                              http://item.taobao.com/item.htm?spm=...id=20618475034 ( Variante mit 3 Klemmen auf der RS485 nehmen!)
                              Bucht: leadme-eshop ca. 16€

                              Gruß Stephan

                              Kommentar


                                #45
                                Hi,

                                erstmal vielen Dank für eure Bemühungen bei diesem Plugin. Ich versuche derzeit das Plugin mit der Zehnder 350 zum Laufen zu bringen und komme irgendwie nicht weiter. Vielleicht habt ihr ja noch einen Tipp für mich.

                                Laut Konsole erhalte ich folgende Werte:

                                Code:
                                2014-06-18 11:02:02,349 INFO     Connections  ComfoAir: connected to 192.168.3.253:5555 -- __init__.py:log_info:494
                                2014-06-18 11:02:26,984 DEBUG    Scheduler    ComfoAir-cyclic next time: 2014-06-18 11:02:56+02:00 -- scheduler.py:_next_time:289
                                2014-06-18 11:02:56,660 DEBUG    Scheduler    ComfoAir-cyclic next time: 2014-06-18 11:03:26+02:00 -- scheduler.py:_next_time:289
                                2014-06-18 11:03:26,334 INFO     ComfoAir-cyclic ComfoAir: Triggering cyclic read command: ReadExtractAirRPM -- __init__.py:log_info:494
                                2014-06-18 11:03:26,339 INFO     ComfoAir-cyclic ComfoAir: Preparing command ReadExtractAirRPM with value None (transformed to value byte '') to be sent. -- __init__.py:log_info:494
                                2014-06-18 11:03:26,344 INFO     ComfoAir-cyclic ComfoAir: Successfully sent packet: 07:f0:00:0b:00:b8:07:0f -- __init__.py:log_info:494
                                2014-06-18 11:03:26,348 DEBUG    ComfoAir-cyclic ComfoAir: Trying to receive 5 bytes for the first part of the response. -- __init__.py:log_debug:491
                                2014-06-18 11:03:26,846 DEBUG    Scheduler    ComfoAir-cyclic next time: 2014-06-18 11:03:56+02:00 -- scheduler.py:_next_time:289
                                2014-06-18 11:03:28,355 ERROR    ComfoAir-cyclic ComfoAir: send_command failed: error receiving first part of packet: timeout -- __init__.py:log_err:497
                                2014-06-18 11:03:28,362 INFO     ComfoAir-cyclic ComfoAir: Triggering cyclic read command: ReadComfortTemperature -- __init__.py:log_info:494
                                2014-06-18 11:03:28,369 INFO     ComfoAir-cyclic ComfoAir: Preparing command ReadComfortTemperature with value None (transformed to value byte '') to be sent. -- __init__.py:log_info:494
                                2014-06-18 11:03:28,374 ERROR    ComfoAir-cyclic ComfoAir: send_command failed: No connection to ComfoAir. -- __init__.py:log_err:497
                                2014-06-18 11:03:32,393 INFO     Connections  ComfoAir: connected to 192.168.3.253:5555 -- __init__.py:log_info:494
                                D.h. er schafft es eine Verbindung herzustellen, aber kann keine Werte empfangen. Ich vermute es liegt irgendwie an meinen Einstellungen beim Moxa NPort (siehe Dateianhang).

                                Habt ihr einen Tipp für mich?

                                Danke schon mal!
                                Angehängte Dateien

                                Kommentar

                                Lädt...
                                X