Ankündigung

Einklappen
Keine Ankündigung bisher.

Bus via TCP lesen

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

    Bus via TCP lesen

    Hallo zusammen, hoffe es kann mir hier jemand helfen. Ich habe schon einige Tage mit Versuchen hinter mir und keine Idee mehr. Ich glaube das Handbuch kann ich auch bald auswendig.

    Ich steuere den EibPC via TCP. Beim Schreiben geht das, beim Lesen kommt jedoch nichts zurück.

    Zuerst das Programm zum Empfang der TCP-Telegramme:

    Code:
    [FONT=courier new]if (event(readtcp(Rec_Port,Rec_IP,RawTcpString))) then {
      Pos = find(RawTcpString, $=$, 0u16);
      RawGad = split(RawTcpString, 2u16, Pos - 1u16);
      RawVal = split(RawTcpString, Pos + 1u16, size(RawTcpString) - 1u16);
      IntGad = convert(RawGad, 0u16);
      Command = split(RawTcpString, 0u16, 1u16);
    [B]  // Dies reagiert wie erwartet:[/B]
      if (Command == $W|$c2) then {
        write(address(IntGad), convert(RawVal, 0b01));
        RawTcpString = $Success Binaer$;
        sendtcp(Rec_Port, Rec_IP, RawTcpString);
      } endif;
    [B]  // Dies reagiert leider nicht wie erwartet:[/B]
      if (Command == $R|$c2) then {
        ResultTcpString = $Received:$;
    [B]    // soll Leseanforderung auslösen[/B]
        read(address(IntGad));
        if event(address(IntGad)) then {
           ResultTcpString = ResultTcpString +       convert(address(IntGad), $$c100);
           sendtcp(Rec_Port, Rec_IP, ResultTcpString);
        } endif;
      } endif;
    } endif[/FONT]
    Ich sende sowas wie "W|4827=1", 4827 ist die numerische Form der GA. Das funktioniert prima, schaltet und gibt Erfolgsmeldung zurück.

    Wenn ich aber "R|4827=0" sende (der Wert wird ignoriert), wird zwar die Leseanforderung auf den Bus gesendet und der Aktor antwortet auch, aber das event löst nicht aus und der TCP-Channel bekommt keine Antwort.

    So sieht diese Leseanforderung im Message-Fenster vom EibStudio aus:

    % 2018-09-06 22:21:08 | Sender: EibPC | GA: "Ventil Nachspeisung Pool-0/2/55" | Value: ?% | Type: ?% | Read
    % 2018-09-06 22:21:08 | Sender: 1.0.235 | GA: "Ventil Nachspeisung Pool-0/2/55" | Value: OFF | Type: binary value | Reply


    (4827 ist die GA, die hier aufgelöst wird)

    An dem Eintrag "Sender: 1.0.235..." erkenne ich doch, dass der Aktor geantwortet hat. Den Wert "OFF" hätte ich gern erfragt.

    Warum löst "if event(address(IntGad)) then { ... }" nicht aus?

    Wenn ich mein "sendtcp" außerhalb des "if" platziere, bekomme ich eine Antwort (aber ohne Wert), also der TCP-Channel funktioniert.

    Für alle, die es interessiert, mein Client nutzt NodeJs/JavaScript:

    Code:
    [FONT=courier new]'use strict';
    var net = require('net');
    const REMOTE_CLOUD_HOSTNAME = '192.168.0.12'; // Mein EibPc lauscht hier
    const REMOTE_CLOUD_HOSTPORT = 8114; // und das ist der Port
    const WRITE_COMMAND = "W";
    const DEBUG_COMMAND = "V";
    const SCENE_COMMAND = "N";
    const DIMME_COMMAND = "D";
    const READ_COMMAND = "R";
    // ---- outbound -----
    function sendKnx(ga, v, type, callback) {
      var noreply = type != READ_COMMAND;
      // Kommando hat den Aufbau W|4827=1 oder R|3245=xx (xx wird ignoriert), das Lesen löst ein UDP-Paket im EibPC aus
      // Kommando hat den Aufbau V|4827=1 ist W mit Debug-Email
      // Kommando hat den Aufbau N|4827=5 ist W mit u08 Wert für Szenen
      // Kommando hat den Aufbau D|4827=5 ist W mit u16 Wert für Dimmer
      if (ga && type) {
         // make numerical ga from convenient one
         var parts = ga.split('/');
         if (parts.length !== 3) {
           console.log('**** Data invalid. Ga must have 3 parts');
           return;
         } else {
         var hi = +parts[0];
         var mi = +parts[1];
         var lo = +parts[2];
         if (hi > 255 || mi > 255 || lo > 255 ){
           console.log('**** Data invalid. Ga must have all values <= 255');
           return;
         }
         var gnumerical = hi * 2048 + mi * 256 + lo;
         // each time we send a package we connect, send, and close in one step
         // This is EibPC
         console.log(`**** Connect using ${gnumerical} = ${ga}`);
         try {
           var client = new net.Socket();
           client.on('data', function (data) {
             console.log('Received TCP Response from EibPC: ' + data);
             client.destroy(); // kill client after server's response
             callback(data);
           });
           client.on('close', function () {
           console.log('TCP Connection to EibPC closed');
           // call the caller back that it's now save to return
           callback('Close');
         });
         console.log('**** Socket created');
         client.connect(REMOTE_CLOUD_HOSTPORT, REMOTE_CLOUD_HOSTNAME, function () {
         console.log(`**** Send Data ${gnumerical}=${v}`);
         client.write(`${type}|${gnumerical}=${v}`);
         callback('Sent');
         });
       } catch (Error) {
         console.error(`**** TCP sending failed: ${Error}`);
       }
      }
     }
    }
    // Test
    sendKnx('0/2/55', 0, 'R', (d) => console.log(d));[/FONT]
    Herzlichen Dank für jede Idee...
    Zuletzt geändert von joergkrause; 06.09.2018, 21:47.

    #2
    Hallo,
    der Code müsste sein
    Code:
    if (event(readtcp(Rec_Port,Rec_IP,RawTcpString))) then {
    Pos = find(RawTcpString, $=$, 0u16);
    RawGad = split(RawTcpString, 2u16, Pos - 1u16);
    RawVal = split(RawTcpString, Pos + 1u16, size(RawTcpString) - 1u16);
    IntGad = convert(RawGad, 0u16);
    Command = split(RawTcpString, 0u16, 1u16);
    // Dies reagiert wie erwartet:
    if (Command == $W|$c2) then {
    write(address(IntGad), convert(RawVal, 0b01));
    RawTcpString = $Success Binaer$;
    sendtcp(Rec_Port, Rec_IP, RawTcpString);
    } endif;
    // Dies reagiert leider nicht wie erwartet:
    if (Command == $R|$c2) then {
    ResultTcpString = $Received:$;
    // soll Leseanforderung auslösen
    read(address(IntGad));
    } endif;
    } endif
    
    // Asynchorn zu
    // if (event(readtcp(Rec_Port,Rec_IP,RawTcpString))) then {... }
    if event(address(IntGad)) then {
    ResultTcpString = ResultTcpString + convert(address(IntGad), $$c100);
    sendtcp(Rec_Port, Rec_IP, ResultTcpString);
    } endif;
    Da du in if (event(readtcp()) {} erst die Leseanfrage schickst, musst Du außerhalb dieser If Abfrage auf die einkommende Nachricht warten
    offizielles Supportforum für den Enertex® EibPC: https://knx-user-forum.de/eibpc/
    Enertex Produkte kaufen

    Kommentar


      #3
      Vielen Dank, der Tipp mit der Platzierung außerhalb war entscheidend. Allerdings reicht das nicht, ich habe es jetzt so implementiert:

      Code:
      CheckGad = 0u16
      if IsReading == 1b01 and event(readknx(CheckGad, ResultInfo)) then {
          if (IntGad == CheckGad) then {
              sendtcp(Rec_Port, Rec_IP, ResultInfo);
              IsReading = 0b01;
          } endif;
      } endif;
      Der Trick ist, dass ich immer nur auf einen Request reagieren kann, um auf dem passenden Port zu antworten. Im CF Makro sieht man, wie das als Stack implementiert wird, aber das war hier erstmal nicht notwendig. Wer es probiert, sollte beachten, dass der nächste Request erst gesendet werden darf, wenn der vorhergehende beantwortet wurde. IsReading blockiert einfach solange. Der Vergleich auf die aktuelle Gruppenadresse ist eine zusätzliche Sicherung, damit der Sender lieber nichts statt falscher Werte bekommt.

      Kommentar

      Lädt...
      X