Modul für Netgear Arlo-Kameras (Python-Version)

Begonnen von maluk, 07 Mai 2018, 20:40:06

Vorheriges Thema - Nächstes Thema

mi.ke

FHEM 5.9 | RPi4 + 5 x RPi(Z) + FB7590 + FB 6890 LTE via LAN und WAN (VPN) verbunden.
2 x CUL868 + 3 x RFXTRX(e) + 6 x HMwLanGW + 4 x z2tGw + 5 x LGW + 2 x IRBlast + CO2 +++
FS20, FHT, FMS, Elro(mod), CM160, Revolt, LGTV, STV, AVR, withings, HM-sec-*, HM-CC-RT-DN, AMAD, PCA301, arlo, Aqara

Niko1987

kann es sein das mein Telnet hier nichts durchlässt?

Gruß
Flo

Hembo

So ich frage mich gerade ob ich der einzige bin der das Problem hat:

über set arm / disarm, sowie Sirene etc. funktioniert super! Jedoch wenn ich versuche einen Modus anzusprechen klappt nichts. Auch wenn ich den Modus in der Arlo App auswähle bleibt der letzte Status laut state reading bestehen. Ein statusrefresh habe ich natürlich gemacht, genauso wie den Server neu gestartet & den ganzen Pi. Wenn ich arm / disarm in der Arlo app anklicke wird es auch problemlos an FHEM übertragen. Stehe etwas auf dem Schlauch, da ich die Modis gern für FHEM->homekit verwenden würde...

Dann noch kurz die Frage ob es möglich ist die Bewegung der Kameras abzufragen ohne Aufzeichnung (in der App eine Regel mit Bewegungserkennung aber ohne Video -> verursacht eine Push Meldung ohne Aufzeichnung - sehe ich jedoch im Kamera Reading nicht)

Vorerst vielen Dank für Eure Hilfe

Und ein RIEEEEESEN DANK dafür dass es das Modul überhaupt gibt!!

sparkiie

Ich habe das Modul vor einigen Tagen installiert und hatte auch ständig das Problem, dass der Server abgestürzt. Readings und Befehle sind dadurch natürlich nicht durchgegangen.

Nun habe ich heute alles noch einmal neu aufgesetzt und bekomme es gar nicht mehr ans laufen. Nicht einmal die Basis wird per Autocreate angelegt.

Log im FHEM sagt:
Traceback (most recent call last):
  File "FHEM/49_Arlo.py", line 406, in <module>
    main(sys.argv[1:])
  File "FHEM/49_Arlo.py", line 402, in main
    startService(int(argv[3]))
  File "FHEM/49_Arlo.py", line 373, in startService
    server.socket.close()
NameError: global name 'server' is not defined
2018.10.12 20:05:02 2: Error occured when calling Arlo daemon: http://localhost:8001/ACCOUNT?device=Arlo_Cloud&cmd=autocreate&basestationId=&cameraId=: Select timeout/error:


Arlo Log:
2018-10-12 20:04:48,407 INFO: Start event handler

sparkiie

#169
Irgendwie hat er die Basis nun gefunden.

Im Arlo Log steht:
Errno32: Brocken pipe

Allerdings läuft die Cloud auf Port 8001 und FHEM Telnet Port ist 7020.
Beim definieren der Cloud wird die Port Info als 3. Argument ignoriert. Den FHEM Port kann ich nicht auf 8001 stellen:
telnetPort: Can't open server port at 8001: Address already in use

Heartbeat auf 90 hat nichts geändert.

Niko1987

Guten morgen,

bei mir klappt es jetzt einigermaßen:

Mein Landroid Mähroboter hat den Port 8001 belegt.
Das hab ich per SSH mit netstat --tcp --listening --programs --numeric rausgefunden.
Um den Port für das Arlo Modul zu ändern hat es bei mir nicht ausgereicht den Port als 3. Argument beim define anzugeben.
Ich musste zusätzlich im 49_Arlo.pm den Port ändern.

$hash->{DEF} = "ACCOUNT $cryptUser $cryptPasswd";
      $hash->{SERVER_PORT} = "8002";


danach das Modul neu laden und mir define Arlo_Cloud Arlo ACCOUNT hans.mustermann@xyz.de meinPasswort 8002 das Device anlegen.

Seit dem klappt die Verbindung.

Ich wollte mal testweise in der Datei /usr/local/lib/python2.7/dist-packages/Arlo.py in Zeile 58 pass durch raise ersetzen.
Jedoch befindet sich in meinem Fall in diesem Ordner keine Arlo.py.
Ist diese Datei versteckt?.

Bei mir tauchen diese Meldungen bei jedem updateReadings im FileLog auf.
127.0.0.1 - - [13/Oct/2018 08:37:41] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=4RD17278A053E&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [13/Oct/2018 08:38:41] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=xxx&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [13/Oct/2018 08:39:41] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=xxx&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [13/Oct/2018 08:40:41] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=xxx&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [13/Oct/2018 08:41:41] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=xxx&cameraId= HTTP/1.0" 200 -



hin und wieder auch:
127.0.0.1 - - [13/Oct/2018 06:18:08] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=xxx&cameraId= HTTP/1.0" 200 -
Exception in thread HeartbeatThread:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/local/lib/python2.7/dist-packages/Arlo.py", line 305, in Heartbeat
    self.Ping(basestation)
  File "/usr/local/lib/python2.7/dist-packages/Arlo.py", line 408, in Ping
    return self.NotifyAndGetResponse(basestation, {"action":"set","resource":"subscriptions/"+self.user_id+"_web","publishResponse":False,"properties":{"devices":[basestation_id]}})
  File "/usr/local/lib/python2.7/dist-packages/Arlo.py", line 388, in NotifyAndGetResponse
    transId = self.Notify(basestation, body)
  File "/usr/local/lib/python2.7/dist-packages/Arlo.py", line 379, in Notify
    self.request.post('https://arlo.netgear.com/hmsweb/users/devices/notify/'+body['to'], body, headers={"xcloudId":basestation.get('xCloudId')})
  File "/usr/local/lib/python2.7/dist-packages/Arlo.py", line 158, in post
    return self._request(url, 'POST', params, headers, raw)
  File "/usr/local/lib/python2.7/dist-packages/Arlo.py", line 137, in _request
    r = self.session.post(url, json=params, headers=headers)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 559, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 512, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 622, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 495, in send
    raise ConnectionError(err, request=request)
ConnectionError: ('Connection aborted.', error("(104, 'ECONNRESET')",))


Vielen Dank für eure Hilfe

Gruß
Flo

sparkiie

Ich bin mittlerweile sich ein Stück weiter.
Meine Readings etc. funktionieren immer für ca. 2-3h. Danach muss ich das Telnet Password neu setzen, den Server stoppen und wieder starten. Dann geht es wieder ein passt Stunden!

Wo liegt denn das  Problem?

maluk

Zitat von: Hembo am 12 Oktober 2018, 15:57:44
über set arm / disarm, sowie Sirene etc. funktioniert super! Jedoch wenn ich versuche einen Modus anzusprechen klappt nichts. Auch wenn ich den Modus in der Arlo App auswähle bleibt der letzte Status laut state reading bestehen. Ein statusrefresh habe ich natürlich gemacht, genauso wie den Server neu gestartet & den ganzen Pi. Wenn ich arm / disarm in der Arlo app anklicke wird es auch problemlos an FHEM übertragen. Stehe etwas auf dem Schlauch, da ich die Modis gern für FHEM->homekit verwenden würde...

Ein Modus wird in der Form set <Basisstation> mode <Modus-Name aus App>, also z.B. set Arlo_Basisstation mode Terrasse, falls der Modus in der App den Namen Terrasse hat. Hast du das so gemacht? Falls ja, kam irgendeine Fehlermeldung in /tmp/arlo.log oder im FHEM-Log?

maluk

#173
Zitat von: Niko1987 am 13 Oktober 2018, 09:26:00
danach das Modul neu laden und mir define Arlo_Cloud Arlo ACCOUNT hans.mustermann@xyz.de meinPasswort 8002 das Device anlegen.

Dass die Port-Angabe ignoriert wird, ist ein Bug, den ich gerade behoben habe. Die neue Version habe ich hochgeladen.

Zitat
Ich wollte mal testweise in der Datei /usr/local/lib/python2.7/dist-packages/Arlo.py in Zeile 58 pass durch raise ersetzen.
Jedoch befindet sich in meinem Fall in diesem Ordner keine Arlo.py.
Ist diese Datei versteckt?.

Suche einfach, wo die Datei bei dir liegt: sudo find / -name Arlo.py

Zitat
Bei mir tauchen diese Meldungen bei jedem updateReadings im FileLog auf.
127.0.0.1 - - [13/Oct/2018 08:37:41] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=4RD17278A053E&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [13/Oct/2018 08:38:41] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=xxx&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [13/Oct/2018 08:39:41] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=xxx&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [13/Oct/2018 08:40:41] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=xxx&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [13/Oct/2018 08:41:41] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=xxx&cameraId= HTTP/1.0" 200 -


Das ist das typische Verhalten nach Verbindungsabbrüchen. Der Python-Server hat eine Dauerverbindung zum Arlo-Server. Mein Python-Server nimmt Befehle entgegen und sendet sie zum Arlo-Server. Der Background-Thread mit der Dauerverbindung erhält normalerweise dann die Status-Änderung vom Arlo-Server. Diese Rückmeldungen wäre dann im Logfile zu sehen. Wenn der Thread aber vorher abgestürzt ist, funktioniert das nicht mehr.

Eigentlich habe ich etwas eingebaut, dass die Verbindung neu aufgebaut wird, wenn sie abbricht, aber das funktioniert nicht immer. Leider ist das alles sehr schwer zu reproduzieren, daher konnte ich das Problem bisher noch nicht lösen. Aber ich werde mich auf jeden Fall noch darum kümmern, da es natürlich nervig ist, wenn man nie genau weiß, ob das Modul jetzt gerade funktioniert oder nicht.

sparkiie

Zitat von: maluk am 14 Oktober 2018, 09:04:52
Eigentlich habe ich etwas eingebaut, dass die Verbindung neu aufgebaut wird, wenn sie abbricht, aber das funktioniert nicht immer. Leider ist das alles sehr schwer zu reproduzieren, daher konnte ich das Problem bisher noch nicht lösen. Aber ich werde mich auf jeden Fall noch darum kümmern, da es natürlich nervig ist, wenn man nie genau weiß, ob das Modul jetzt gerade funktioniert oder nicht.

Vielen Dank für deine Arbeit!

Ich Frage mich, inwiefern die Abbrüche mit dem Telnet vom FHEM zu tun haben. Ich muss nach jedem Abbruch etwas am Telnet ändern (z.B. ein Passwort setzen) oder FHEM neu starten, damit ich die Basis wieder ansprechen kann!

maluk

Hast du mehrere Telnet-Devices definiert? Der Telnet-Port wird ermittelt, indem das erste Telnet-Device, das nicht das interne Attribut TEMPORARY gesetzt hat, gelesen wird. Für mich sieht es so aus, als ob es bei dir ein weiteres Telnet-Device gibt und du durch die Änderung des Telnet-Ports das richtige Device wieder auf Platz 1 bringst.

maluk

Zitat von: Niko1987 am 13 Oktober 2018, 09:26:00
127.0.0.1 - - [13/Oct/2018 06:18:08] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=xxx&cameraId= HTTP/1.0" 200 -
Exception in thread HeartbeatThread:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/local/lib/python2.7/dist-packages/Arlo.py", line 305, in Heartbeat
    self.Ping(basestation)
...


Das Muster, dass der Verbindungsabbruch durch den Heartbeat verursacht wird, zieht sich sowohl durch Eure Meldungen als auch meine Verbindungsabbrüche, die allerdings deutlich seltener auftreten als hier beschrieben. Es sieht für mich so aus, als ob ein Verbindungsfehler im Heartbeat dazu führt, dass der Heartbeat-Thread komplett abstürzt und dadurch keine Heartbeat-Signale mehr an den Arlo-Server gesendet werden. Dadurch wird der Arlo-Server vermutlich irgendwann einfach die Verbindung abbrechen.

Das Exception Handling im Heartbeat-Thread ist quasi nicht vorhanden. Daher habe ich Modul /usr/local/lib/python2.7/dist-packages/Arlo.py in Zeile 308 folgende 2 Zeilen eingefügt:


                except Exception as e:
                    print(e)


Die modifizierte Heartbeat-Methode sieht jetzt also wie folgt aus:


        def Heartbeat(self, stop_event):
            while not stop_event.wait(90.0):
                try:
                    self.Ping(basestation)
                except queue.Empty:
                    pass
                except Exception as e:
                    print(e)


Es wäre super, wenn Ihr die Anpassung bei Euch auch vornehmen und danach den Python-Server neu starten könntet. Falls dies die Lösung ist, werde ich dies an Jeffrey Walter melden, der ja der Autor des Python-Moduls ist, das ich intern verwende.

sparkiie

Zitat von: maluk am 14 Oktober 2018, 09:33:36
Hast du mehrere Telnet-Devices definiert? Der Telnet-Port wird ermittelt, indem das erste Telnet-Device, das nicht das interne Attribut TEMPORARY gesetzt hat, gelesen wird. Für mich sieht es so aus, als ob es bei dir ein weiteres Telnet-Device gibt und du durch die Änderung des Telnet-Ports das richtige Device wieder auf Platz 1 bringst.

Ich nutze bewusst keine anderen Telnet-Devices.
Bei Verwendung eines Telnet Passwort werden devices wie telnetforblockingfn###### angelegt.
Im Moment läuft es ohne Passwort und einem at, das den Server jede Stunde stoppt und wieder startet.

Allerdings hat es sich über Nacht auch wieder aufgehangen....

maluk

Zitat von: sparkiie am 14 Oktober 2018, 10:09:06
Ich nutze bewusst keine anderen Telnet-Devices.
Bei Verwendung eines Telnet Passwort werden devices wie telnetforblockingfn###### angelegt.
Im Moment läuft es ohne Passwort und einem at, das den Server jede Stunde stoppt und wieder startet.

Allerdings hat es sich über Nacht auch wieder aufgehangen....

Ich beschreibe mal kurz, was intern passiert: es werden alle telnet-Devices durchsucht und aus dem ersten Telnet-Device ohne TEMPORARY-Internal wird das interne Attribut PORT gelesen. Dies ist dann der Telnet-Port, über den kommuniziert wird. Danach werden die allowed-Devices durchsucht, bis ein Device gefunden wird, das im Attribut validFor das vorher gefundene Telnet-Device stehen hat. Falls ein solches allowed-Device gefunden wir, wird das Attribut password als Telnet-Passwort verwendet.

Vielleicht hilft dir diese Beschreibung bei der Fehlersuche. Alternativ kann ich mein Modul auch so anpassen, dass man optional Telnet-Port und Telnet-Passwort manuell angeben kann, dann hast du es selbst in der Hand, mit welchen Parametern der Server aufgerufen wird.

Wichtig: der Port, den man im Cloud-Device angebeben kann, ist nicht der Telnet-Port sondern der Port, unter dem der Python-Server-Prozess läuft. Dieser muss auf jeden Fall vom Telnet-Port abweichen, da dieser von FHEM belegt ist.

Niko1987

Servus,

danke. Hab das mal geändert.

Mal sehen :) Im Log bleibt aber immernoch ein eintrag bei jedem UpdateReadings und bei jedem cmd an eine Cam

127.0.0.1 - - [14/Oct/2018 15:10:59] "GET /BASESTATION?device=Arlo_Arlo&cmd=updateReadings&basestationId=xxx&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [14/Oct/2018 15:13:25] "GET /BASESTATION?device=Arlo_Arlo&cmd=arm&basestationId=xxx&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [14/Oct/2018 15:13:44] "GET /BASESTATION?device=Arlo_Arlo&cmd=disarm&basestationId=xxx&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [14/Oct/2018 15:13:45] "GET /BASESTATION?device=Arlo_Arlo&cmd=disarm&basestationId=xxx&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [14/Oct/2018 15:13:48] "GET /BASESTATION?device=Arlo_Arlo&cmd=arm&basestationId=xxx&cameraId= HTTP/1.0" 200 -
127.0.0.1 - - [14/Oct/2018 15:13:52] "GET /CAMERA?device=Arlo_Hof&cmd=off&basestationId=xxx&cameraId=4N7167SKCDA8D HTTP/1.0" 200 -
127.0.0.1 - - [14/Oct/2018 15:13:55] "GET /CAMERA?device=Arlo_Hof&cmd=on&basestationId=xxx&cameraId=xxxHTTP/1.0" 200 -


Gruß
Flo