FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: Shadow3561 am 28 Februar 2023, 19:28:50

Titel: !! Gelöst !! Terminal Curl Aufruf in reading speichern
Beitrag von: Shadow3561 am 28 Februar 2023, 19:28:50
Ich komme nicht weiter.

Ich besitze eine Hikvision IP Video Doorbell.
Diese lässt sich leider nicht in FHEM einbinden und eine API kann ich auch nirgends finden.
Nach langem suchen habe ich es nun geschafft den Status der Klingeltaste per curl ab zu fragen.

Der Aufruf im Terminal lautet
curl -i --digest -u admin:password http://192.168.1.xxx/ISAPI/VideoIntercom/callStatus?format=json&channelType=tripartitePlatform

Die Ausgabe sieht so aus

Type=tripartitePlatform
[1] 138193
root@intelnuc:~# HTTP/1.1 401 Unauthorized
Date: Tue, 28 Feb 2023 19:21:00 GMT
Server: webs
Content-Length: 0
Connection: close
X-Frame-Options: SAMEORIGIN
Cache-Control: no-store
Pragma: no-cache
WWW-Authenticate: Digest qop="auth", realm="DS-4Dxxxxx", nonce="OTdlOWU3MGM5M2RhYTc5MDJkxxxxxxxxxx=", stale="false", opaque="", domain="::"
Content-Type: application/json

HTTP/1.1 200 OK
Date: Tue, 28 Feb 2023 19:21:00 GMT
Server: webs
Content-Length: 42
Connection: close
X-Frame-Options: SAMEORIGIN
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/json

{
"CallStatus": {
"status": "idle"
}
}


Ich benötige also den Status.

Leider lässt sich die Abfrage der URL nicht per HTTPMOD auslesen weil es mit der Authentifizierung nicht klappt, oder ich bin einfach zu dusselig.

Nun war mein Gedanke es mit folgenden Aufruf in FHEM zu versuchen

{qx(curl -i --digest -u admin:password http://192.168.1.xxx/ISAPI/VideoIntercom/callStatus?format=json&channelType=tripartitePlatform)}
eine Eingabe in der Kommandozeile schreibt auch eine Ausgabe ins LOG. Nun hätte ich es aber gerne in einem Reading von einem Dummy damit ich auf das event reagieren kann. und genau dort komme ich nicht weiter.

Wie stelle ich es an, dass der Status der Klingel in einem reading landet?

Ich hoffe auf eure Hilfe und bedanke mich im Voraus.
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: JoWiemann am 28 Februar 2023, 19:38:58
Hallo,

Du kannst das über ein userReadings machen. Allerdings glaube ich nicht, dass Dir das hilft. Der Aufruf über curl polled ja nicht, sondern ist nur ein Snapshot. Somit wirst Du das drücken der Taste eher nicht mitbekommen.

Grüße Jörg

PS: es gibt wohl auch ein SDK, Install Hikvision Device Network SDK. Viel habe ich dazu aber auch nicht gefunden: https://github.com/laszlojakab/hikvision-intercom-python-demo
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Shadow3561 am 28 Februar 2023, 19:41:17
Dafür habe ich ein "at" geplant was alle 30sec den Status triggert.

Das setzt allerdings voraus, dass ich es irgendwie schaffe den Status in ein Userreading zu bekommen. Daran hakt es leider
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: JoWiemann am 28 Februar 2023, 19:46:28
Murphy sagt: der Taster wird immer gedrückt wenn das at wartet.
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Shadow3561 am 28 Februar 2023, 19:58:40
Aber Murphy weiss nicht, dass der Taster als gedrückt angezeigt wird, solange es Klingelt. Und die dauert 60sec. Da hat das at 1-2x die Gelegenheit ein klingeln zu erwischen.
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: JoWiemann am 28 Februar 2023, 20:11:11
Ich bin jetzt nicht der httpmod Kenner. Eventuell mal im httpmod Thread die Frage nach dem richtigen Aufruf stellen.

Hast Du schon mal folgendes Probiert? Httpmod mit

http://admin:passwort@192.168.1.xxx/ISAPI/VideoIntercom/callStatus?format=json&channelType=tripartitePlatform

aufzurufen?

Grüße Jörg
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Otto123 am 28 Februar 2023, 20:19:17
Zitat von: Shadow3561 am 28 Februar 2023, 19:28:50
Wie stelle ich es an, dass der Status der Klingel in einem reading landet?
das schreibt die IPv4 Adresse in einen Dummy
setreading Test IP {(qx(curl http://v4.ident.me))}
So kommt unnützes "Beiwerk" dazu (ich weiß nicht wozu Du den Parameter -i genommen hast?) setreading Test IP {(qx(curl -i http://v4.ident.me))}
Und so landet keine Statusmeldung (alle 30 sec :) ) im Log
setreading Test IP {(qx(curl -s http://v4.ident.me))}

Der Syntax für set(reading) steht in der commandref https://fhem.de/commandref_modular_DE.html#set

Aber das geht mit httputils auch anders / ohne blockierenden Shell Aufruf.
https://wiki.fhem.de/wiki/HttpUtils
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: betateilchen am 28 Februar 2023, 20:24:10
Und wieder meine Frage: warum curl und nicht GetFileFromUrl() als FHEM-Bordmittel?
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Shadow3561 am 01 März 2023, 05:38:22
Zitat von: betateilchen am 28 Februar 2023, 20:24:10
Und wieder meine Frage: warum curl und nicht GetFileFromUrl() als FHEM-Bordmittel?

Weil ich den Aufruf nicht verstehe. Irgendwie schaffe ich es nicht die Autorisierung mit einzubauen.
Die Anfrage mit User:pass@ip klappt leider bei der Klingel nicht nicht und gibt einen Fehler zurück.

Mit freundlichen Grüßen
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Benni am 01 März 2023, 07:10:46
Wenn ich es richtig sehe, ist die Anmeldung ja lediglich Basic Auth, das kann HTTPMOD doch auch:

Zitat
Handling sessions and logging in

In simple cases logging in works with basic authentication. In the case HTTPMOD accepts a username and password as part of the URL in the form http://User:Password@192.168.1.18/something

<...>

Dann sollte das mit folgender HTTMOD-Definition doch eigentlich funktionieren, sofern der im Eingangspost gezeigte Curl-Aufruf funktioniert hat:


defmod htKlingel HTTPMOD http://admin:ann-sophie@192.168.1.26/ISAPI/VideoIntercom/callStatus?format=json&channelType=tripartitePlatform 30
attr htKlingel enforceGoodReadingNames 1
attr htKlingel event-on-change-reading .*
attr htKlingel extractAllJSON 1


gb#
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Shadow3561 am 01 März 2023, 07:42:50
ZitatDie Anfrage mit User:pass@ip klappt leider bei der Klingel nicht nicht und gibt einen Fehler zurück.


Zitat von: Benni am 01 März 2023, 07:10:46
Wenn ich es richtig sehe, ist die Anmeldung ja lediglich Basic Auth, das kann HTTPMOD doch auch:

Dann sollte das mit folgender HTTMOD-Definition doch eigentlich funktionieren, sofern der im Eingangspost gezeigte Curl-Aufruf funktioniert hat:


Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Otto123 am 01 März 2023, 08:41:49
Zitat von: Shadow3561 am 01 März 2023, 05:38:22
Irgendwie schaffe ich es nicht die Autorisierung mit einzubauen.
Die Anfrage mit User:pass@ip klappt leider bei der Klingel nicht nicht und gibt einen Fehler zurück.
mMn ist der Unterschied: Im Aufruf mit curl -u werden Sonderzeichen weitgehend akzeptiert, ergo kann der Account z.B. eine Email Adresse sein (Sonderzeichen wie @ enthalten ) in der url müsste man alle Sonderzeichen "url codieren" - Beispiel: aus @ wird %40.
Gleiches gilt für Sonderzeichen im Passwort.

Siehe auch https://wiki.fhem.de/wiki/HttpUtils#GetFileFromURL
ZitatWICHTIG: Falls ein Username sowie Passwort übergeben werden, so müssen diese vorher jeweils mittels urlEncode() in URL-kompatible Form umgewandelt werden um Probleme mit evtl. enthaltenen Sonderzeichen zu vermeiden.
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Shadow3561 am 01 März 2023, 09:02:21
Mit der Codierung der Sonderzeichen im Passwort (admin:xxx%2dxxxxx funktioniert es auch nicht.

Zurück kommt dann


"requestURL": "/ISAPI/VideoIntercom/callStatus",
"statusCode": 4,
"statusString": "Invalid Operation",
"subStatusCode": "badAuthorization",
"errorCode": 1073741827,
"errorMsg": "The user has not passed the authentication"
}




Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Otto123 am 01 März 2023, 09:33:20
ich dachte jetzt gar nicht das hier im Post die echten Namen und Passwörter stehen :)

Dein curl Aufruf verwendet --digest - da läuft doch die Autorisierung zweistufig (challenge response) wenn ich das richtig verstehe?
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: JoWiemann am 01 März 2023, 09:42:03
Hallo,

ich habe Dir mal etwas gebaut. Ohne Gewähr.

defmod Klingel dummy
attr Klingel readingList Taster



defmod getKlingel at +*00:00:30 {\
my $strCurl = `curl -i --digest -u admin:password "http://192.168.1.xxx/ISAPI/VideoIntercom/callStatus?format=json&channelType=tripartitePlatform"`;;\
$strCurl =~ s/\n|\t//g;;\
\
  if ($strCurl =~ /"CallStatus":{"status":"(.*?)"}/) {\
    fhem("set Klingel Taster $1");;\
  } else {\
    fhem("set Klingel Taster Fehler");;\
  }\
}


Bitte admin:psswort und die IP wieder vervollständigen

Grüße Jörg
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Benni am 01 März 2023, 09:53:51
Zitat von: Otto123 am 01 März 2023, 09:33:20
ich dachte jetzt gar nicht das hier im Post die echten Namen und Passwörter stehen :)

Dein curl Aufruf verwendet --digest - da läuft doch die Autorisierung zweistufig (challenge response) wenn ich das richtig verstehe?

Den hatte ich gar nicht bemerkt!
Das kann HttpUtils (und damit HTTPMOD) anscheinend nicht, wenn ich im Forum ausreichend recherchiert habe.

Das ist auch nicht zweistufig. Dabei werden, wenn ich es richtig verstanden habe, eigentlich nur Name und Passwort vor dem Senden als MD5-Hash encodiert, statt nur einfach in Base64 encodiert.

gb#
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: betateilchen am 01 März 2023, 10:52:15
Zitat von: Benni am 01 März 2023, 09:53:51
Das kann HttpUtils ... anscheinend nicht

wie? wo? was?

Es gibt etwas, was HttpUtils nicht kann? Lass das nicht Rudi hören...  ;D
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Shadow3561 am 01 März 2023, 11:09:32
Damit klappt es zuverlässig. Danke

Wie schaffe ich es, dass nicht das Log zugefülltes wird? Verbose 0 hilft leider nicht.

Zitat von: JoWiemann am 01 März 2023, 09:42:03
Hallo,

ich habe Dir mal etwas gebaut. Ohne Gewähr.

defmod Klingel dummy
attr Klingel readingList Taster



defmod getKlingel at +*00:00:30 {\
my $strCurl = `curl -i --digest -u admin:password "http://192.168.1.xxx/ISAPI/VideoIntercom/callStatus?format=json&channelType=tripartitePlatform"`;;\
$strCurl =~ s/\n|\t//g;;\
\
  if ($strCurl =~ /"CallStatus":{"status":"(.*?)"}/) {\
    fhem("set Klingel Taster $1");;\
  } else {\
    fhem("set Klingel Taster Fehler");;\
  }\
}


Bitte admin:psswort und die IP wieder vervollständigen

Grüße Jörg
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: betateilchen am 01 März 2023, 12:49:45
Zitat von: Shadow3561 am 01 März 2023, 11:09:32
Wie schaffe ich es, dass nicht das Log zugefülltes wird? Verbose 0 hilft leider nicht.

In Deinen fhem() aufrufen den Parameter für quiet angeben.

fhem("mache bla",1)
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: betateilchen am 01 März 2023, 13:08:11
Warum machst Du Dir das Leben mit dem regexen von JSON schwer?
Da kann doch FHEM selbst ein reading generieren.


defmod getKlingel at +*00:00:30 {\
my $strCurl = `curl -i --digest -u admin:password "http://192.168.1.xxx/ISAPI/VideoIntercom/callStatus?format=json&channelType=tripartitePlatform"`;;\
json2reading('Klingel',$strCurl);


Danach steht der Zustand des Tasters als reading "CallStatus_status" im device "Klingel".
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: JoWiemann am 01 März 2023, 13:22:30
Zitat von: betateilchen am 01 März 2023, 13:08:11
Warum machst Du Dir das Leben mit dem regexen von JSON schwer?
Da kann doch FHEM selbst ein reading generieren.


defmod getKlingel at +*00:00:30 {\
my $strCurl = `curl -i --digest -u admin:password "http://192.168.1.xxx/ISAPI/VideoIntercom/callStatus?format=json&channelType=tripartitePlatform"`;;\
json2reading('Klingel',$strCurl);


Danach steht der Zustand des Tasters als reading "CallStatus_status" im device "Klingel".

Ausgehend von der Rückgabe des curl Aufrufs, wie sie im ersten Post hinterlegt worden ist, handelt es sich um kein reines JSON. Also läuft json2reading auf einen Fehler.

Grüße Jörg
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: betateilchen am 01 März 2023, 13:29:12
Ok, da hast Du natürlich recht.

Vielleicht sollte man mal curl dazu bewegen, nur den body zurückzuliefern? Wenn ich mich recht erinnere, gibt es bei curl einen parameter -b, der genau das bewirkt.

Ansonsten wäre es ziemlich sinnfrei, beim Aufruf der URL explizit ein Rückgabeformat (format=json) anzugeben, wenn dann doch kein brauchbares json zurückkommt.


Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: JoWiemann am 01 März 2023, 14:48:37
Zitat von: betateilchen am 01 März 2023, 13:29:12
Vielleicht sollte man mal curl dazu bewegen, nur den body zurückzuliefern? Wenn ich mich recht erinnere, gibt es bei curl einen parameter -b, der genau das bewirkt.

Habe den Parameter gefunden: -H "Accept: application/json". Dann muss aber der Server das auch interpretieren.

Grüße Jörg
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Shadow3561 am 01 März 2023, 14:59:48
-H gibt leider nichts zurück.
-s hingegen liefert


{
"CallStatus": {
"status": "idle"
}
}
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: JoWiemann am 01 März 2023, 15:12:25
Zitat von: Shadow3561 am 01 März 2023, 14:59:48
-s hingegen liefert


{
"CallStatus": {
"status": "idle"
}
}


Dann kannst Du den Vorschlag von betateilchen nehmen: https://forum.fhem.de/index.php/topic,132443.msg1266048.html#msg1266048
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Shadow3561 am 01 März 2023, 18:46:31
Dank eurer Hilfe klappt es jetzt wie gewünscht.

Für die wenigen, die ähnliches vor haben.

Dummy definieren für das gewünschte Reading
defmod HikKlingel dummy


Notify definieren was den Curl-Aufruf macht und den json-String in den Dummy schreibt
defmod getKlingel at +*00:00:30  {\
my $strCurl = `curl -s --digest -u admin:password "http://192.168.1.xxx/ISAPI/VideoIntercom/callStatus?format=json&channelType=tripartitePlatform"`;;;;\
json2reading('HikKlingel',$strCurl);;\
}


Mit dem Reading des Dummy kann man dann weitere Aktionen ausführen.
In meinem Fall wird ein snapshot von einer IP-Cam gemacht

defmod CAMMOTION.not.02 notify HikKlingel:CallStatus_status:.ring {fhem ("get KlingelNeu image")}
attr CAMMOTION.not.02 addStateEvent 1


Vielen Dank noch einmal an alle.

Mit freundlichen Grüßen
Titel: Antw:!! Gelöst !! Terminal Curl Aufruf in reading speichern
Beitrag von: Otto123 am 01 März 2023, 18:51:33
Da käme dann nochmal der Tipp von betateilchen zum tragen:  ;)
https://forum.fhem.de/index.php/topic,132443.msg1266047.html#msg1266047

Sonst hast Du die get Aufrufe alle im Log ...
Titel: Antw:!! Gelöst !! Terminal Curl Aufruf in reading speichern
Beitrag von: Shadow3561 am 01 März 2023, 18:56:12
Zitat von: Otto123 am 01 März 2023, 18:51:33
Da käme dann nochmal der Tipp von betateilchen zum tragen:  ;)
https://forum.fhem.de/index.php/topic,132443.msg1266047.html#msg1266047

Sonst hast Du die get Aufrufe alle im Log ...

Dem ist eben nicht so.
Ich weiss zwar nicht warum, könnte mir aber denken, dass es an json2reading liegt.
Das Log jedenfalls ist ruhig, zu Glück, denn den Tipp von betateilchen habe ich nicht so ganz verstanden und konnte leider weder bei Google noch hier im Forum etwas darüber finden.
Aber vielleicht magst du es ja ergänzen damit Suchende evtl. auf diesen Thread aufmerksam werden wenn sie nach ähnlichem suchen.
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: betateilchen am 01 März 2023, 18:57:05
Zitat von: Shadow3561 am 01 März 2023, 18:46:31
Dummy definieren für das gewünschte Reading

Auf den dummy kann man auch getrost verzichten, wenn es nur darum geht, damit ein notify zu triggern.

Dann kannst Du das reading auch einfach in das at schreiben
json2reading('getKlingel',$strCurl)

und dann das notify darauf definieren - dabei kannst Du sogar komplett auf das fhem() verzichten:
defmod CAMMOTION.not.02 notify getKlingel:CallStatus_status:.ring get KlingelNeu image
Titel: Antw:!! Gelöst !! Terminal Curl Aufruf in reading speichern
Beitrag von: betateilchen am 01 März 2023, 18:59:52
Zitat von: Shadow3561 am 01 März 2023, 18:56:12
denn den Tipp von betateilchen habe ich nicht so ganz verstanden und konnte leider weder bei Google noch hier im Forum etwas darüber finden.

Das ist hier im Forum bereits (gefühlt) 728 mal erklärt.
Du musst den Aufruf der Funktion fhem() um einen zusätzlichen Parameter ergänzen.


fhem ("get KlingelNeu image",1)


Durch das ",1" werden Logausgaben aus der fhem() Funktion unterdrückt.

Aber wie schon geschrieben - in Deinem Fall brauchst Du fhem() überhaupt nicht.


---
Titel: Antw:Terminal Curl Aufruf in reading speichern
Beitrag von: Benni am 02 März 2023, 09:56:20
Zitat von: betateilchen am 01 März 2023, 10:52:15
wie? wo? was?

Es gibt etwas, was HttpUtils nicht kann? Lass das nicht Rudi hören...  ;D

Recht hast du! Ich habe zwischenzeitlich mal noch einen kurzen Blick in HttpUtils geworfen und das kann digest (natürlich! :) )

Das müsste nur noch irgendwie in HTTPMOD Anwendung finden.

gb#