FHEM - Entwicklung > FHEM Development

Saunasteuerung: HttpUtils_NonblockingGet und Cookie mitsenden

(1/1)

xasher:
Hallo zusammen,

ich bin gerade am entwickeln eines Moduls. Gerade bin ich mit Teil 1 fertig. Ich kann die Sauna mittels curl steuern (Annschalten, Ausschalten, Werte wie Temperatur ändern). Dazu hatte ich auch Unterstützung von einem Entwickler von digitalstrom.

Ich hänge gerade bei der Einschaltprozedur. Die läuft im Wesentlichen in 3 Schritten ab:

1) Login und ".ASPXAUTH" Cookie erhalten
2) Get Anfrage mit der SaunaI auf eine URL um ein Antiforgery Cookie zu erhalten (__RequestVerificationToken). Dazu muss das ".ASPXAUTH" Cookie mitgesendet werden.
3) POST Anfrage mit __RequestVerificationToken, PIN (zuvor an der Saunasteuerung festgelegt) und SaunaID

Dann springt die Sauna an. Die Änderung der Werte ist dann über json.

Schritt 1 habe ich zum Test erstmal so (hart)codiert:

--- Code: ---   
    my $header = "Content-Type: application/x-www-form-urlencoded";
    my $datauser   = 'UserName=user&Password=geheim;

    HttpUtils_NonblockingGet({
        url        => AUTHURL,
        ignoreredirects => 1,
        timeout    => 5,
        hash        => $hash,
        method      => "POST",
        header      => $header, 
data => $datauser,
        callback    => \&Klafs_APIAuthResponse,
    }); 
   
}
sub Klafs_APIAuthResponse($) {
    my ($param, $err, $data) = @_;
    my $hash = $param->{hash};
    my $name = $hash->{NAME};
    Log3 $name, 2, "-----------------------------------------------";
    Log3 $name, 2, "COOKIE: $data";
    Log3 $name, 2, "-----------------------------------------------";
    Log3 $name, 2, "-----------------------------------------------";
    Log3 $name, 2, "err: $err";
    Log3 $name, 2, "-----------------------------------------------";
    Log3 $name, 2, "-----------------------------------------------";
    Log3 $name, 2, "header:" . $param->{httpheader};
    Log3 $name, 2, "-----------------------------------------------";
    my $header = $param->{httpheader};
   
    foreach my $cookie ($header =~ m/set-cookie: ?(.*)/gi) {
        Log3 $name, 2, "$name: GetCookies found Set-Cookie: $cookie";
        $cookie =~ /([^,; ]+)=([^,;\s\v]+)[;,\s\v]*([^\v]*)/;
        Log3 $name, 4, "$name: GetCookies parsed Cookie: $1 Wert $2 Rest $3";
        my $name  = $1;
        my $value = $2;
        my $rest  = ($3 ? $3 : "");
        my $path  = "";
        if ($rest =~ /path=([^;,]+)/) {
            $path = $1;
        }
        my $key = $name . ';' . $path;
        $hash->{HTTPCookieHash}{$key}{Name}    = $name;
        $hash->{HTTPCookieHash}{$key}{Value}   = $value;
        $hash->{HTTPCookieHash}{$key}{Options} = $rest;
        $hash->{HTTPCookieHash}{$key}{Path}    = $path;
       
# set Readings
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,'cookie_name',$hash->{HTTPCookieHash}{$key}{Name} );
readingsBulkUpdate($hash,'cookie_value',$hash->{HTTPCookieHash}{$key}{Value} );
readingsBulkUpdate($hash,'cookie_options',$hash->{HTTPCookieHash}{$key}{Options} );
readingsBulkUpdate($hash,'cookie_path',$hash->{HTTPCookieHash}{$key}{Path} );
readingsEndUpdate($hash, 1);
   }
}

--- Ende Code ---
Die Antwort wird ausgewertet - mit viel debugging und in ein Reading geschrieben. Also das ASPXAUTH.

Jetzt bei Anfrage 2 scheitere ich. Wo gebe ich da das ASPXAUTH mit? Ich habs im Header versucht, aber daran gescheitert

--- Code: ---     my $header = ".ASPXAUTH=xxxx";
     my $datauser = 's=11111-2222-3333-ffff-xxxxx';
    HttpUtils_NonblockingGet({
        url        => "https://sauna-app.klafs.com/Control/EnterPin",
        timeout    => 5,
        hash        => $hash,
        method      => "GET",
        header      => $header, 
data => $datauser,
        callback    => \&Klafs_GETantiforgery,
    }); 
   
     # RequestVerificationToken  aus dem Header auslesen für das Cookie
     sub Klafs_GETantiforgery($) {
       my ($param, $err, $data) = @_;
       my $hash = $param->{hash};
       my $name = $hash->{NAME};
       Log3 $name, 2, "COOKIE: $data";
       Log3 $name, 2, "err: $err";
       Log3 $name, 2, "header:" . $param->{httpheader};
     }

--- Ende Code ---

Hier noch der Auszug von den Kollegen von digitalstrom in c

--- Code: ---int klafs_power_on() {
vdc_report(LOG_NOTICE, "network: Power on sauna\n");

struct memory_struct *response = NULL;

char request_body[1024];
strcpy(request_body, "s=");
strcat(request_body, klafs.sauna.id);

response = http_post(url_enterpin, request_body, NULL, klafs.aspxauth); if (response == NULL) { vdc_report(LOG_ERR, "network: getting sauna values failed\n"); return KLAFS_GETREQVERIFYTOKEN_FAILED; } extractRequestVerificationToken(response->memory);
char request_body2[1024];
strcpy(request_body2, "__RequestVerificationToken="); strcat(request_body2, klafs.verificationtoken); strcat(request_body2, "&Pin="); strcat(request_body2, klafs.pin); strcat(request_body2, "&saunaId="); strcat(request_body2, klafs.sauna.id);

response = http_post(url_enterpin, request_body2, NULL, klafs.aspxauth);

if (response == NULL) {
vdc_report(LOG_ERR, "network: power on sauna failed\n"); return KLAFS_CONNECT_FAILED; }

if (strstr(response->memory,"security check") != NULL || strstr(response->memory,"Sicherheitskontrolle") != NULL) { vdc_report(LOG_NOTICE, "security control for sauna not done; cannot power on remotely!\n"); return -1; }

free(response->memory);
free(response);

//get latest sauna values and do a immediate push to DSS; in case power on failed, e.g. security check not done in sauna, isPoweredOn stays "false"
klafs_get_values();
push_binary_input_states();

return 0;
}

--- Ende Code ---

Da wird das cookie in Position 4 bei http_post mitgegeben. Gibts so etwas auch bei HttpUtils_NonblockingGet ?

Vielen Dank schon mal für Ideen

Grüße,
Alex

rudolfkoenig:

--- Zitat ---Da wird das cookie in Position 4 bei http_post mitgegeben. Gibts so etwas auch bei HttpUtils_NonblockingGet ?

--- Ende Zitat ---
Cookies werden als HTTP Header versendet, siehe https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies.
Der header Parameter in HttpUtils_NonblockingGet ist entweder ein String (mit \r\n als Trenner, aber nicht am Ende):

--- Code: ---header => "Content-Type: application/x-www-form-urlencoded\r\n".
          "Cookie: ASPXAUTH=bla; yummy_cookie=choco; tasty_cookie=strawberry",
--- Ende Code ---
oder ein Objekt:

--- Code: ---header => { "Content-Type" => "application/x-www-form-urlencoded",
            "Cookie" => "ASPXAUTH=bla; yummy_cookie=choco; tasty_cookie=strawberry" },

--- Ende Code ---

xasher:
Hallo Rudolf,

Mensch, vielen Dank. Es lag tatsächlich am Syntax "cookie: ....". Das hatte ich nicht vorneangestellt.
Jetzt geht die Sauna an. Prima, so kann ich jetzt arbeiten.

Dankeschön!!!!

Grüße
Alex

Navigation

[0] Themen-Index

Zur normalen Ansicht wechseln