Seite 2 von 3
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Samstag 11. Mai 2019, 21:48
von Sirius3
Die Idee war es, die for-Schleife zu vereinfachen, war dann aber zu einfach.
Du mußt also nur die Funktion verstehen, um sie zu reparieren. Raten ist aber kein guter Weg.
Wegen der zwei Prozesse: Du hast ein Timing-Problem, das mal auftritt und mal nicht, funktioniert hat das also nie wirklich richtig.
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Samstag 11. Mai 2019, 22:01
von __blackjack__
@Homer-S: Welchen Wert muss denn `id` an der Stelle haben wo es am Ende benutzt wird? Und wo bekommst Du diesen Wert her? Ganz sicher nicht durch ein Schlüsselwort was man mal eben davor schreibt. Der Code ist logisch falsch angeordnet. Das muss man durch nachdenken und korrigieren lösen, nicht durch Googlen und/oder raten.
Das mit den beiden Prozessen hat in Deiner Version genau so funktioniert wie jetzt auch. Es wird ein Prozess gestartet der als Server auf einem Port lauscht und fast gleichzeitig einer der sich mit diesem Port verbindet. Das kann immer ”funktionieren”, oder ”nie”, oder mal ja, mal nein. Es ist letztlich Glückssache ob der erste Prozess zu dem Zeitpunkt wo der zweite sich verbinden will, schon soweit ist, oder eben noch nicht. Eine klassische Wettlaufsituation („race condition“) bei nebenläufiger Programmierung. Ich würde da einfach nach dem starten des ersten Prozesses in einer Schleife eine Weile versuchen mich mit dem Port zu verbinden und erst den zweiten Prozess starten, wenn das funktioniert hat. Oder wenn das innerhalb ein oder zwei Sekunden nicht geklappt hat, das Programm mit einer Fehlermeldung abbrechen. Natürlich nach dem beenden des ersten Prozesses.
Und das ``time.sleep(31)`` ist falsch/überflüssig, weil man *erst* auf den `convert`-Prozess warten muss und dann erst den `video`-Prozess terminieren darf. Ja, theoretisch könnte auch das ”immer” funktionieren, muss es aber nicht.
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Samstag 11. Mai 2019, 22:30
von Homer-S
Ich glaube den 'id' Fehler konnte ich lösen. Ganz sicher bin ich mir nict, aber es erscheint mir logisch:
Code: Alles auswählen
def send_message(chatroomids, message=None, photo=None):
""" versendet die Klingelbenachrichtigung """
files = {}
for id in chatroomids:
params = {"chat_id": id}
if message:
params["text"] = message
cmd = "sendMessage"
if photo:
files = {"photo": photo}
cmd = "sendPhoto"
url = TELEGRAM_URL + BOT_TOKEN + "{}{}/{}".format(TELEGRAM_URL, BOT_TOKEN, cmd)
r = requests.get(url, params=params, files=files)
result = r.json()
print(result)
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Montag 13. Mai 2019, 17:45
von Homer-S
Hallo,
ich muss leider schon wieder schreiben. Ich habe mir den Punkt mit den zwei Prozessen zu Herzen genommen.
Gibt es eine Funktion/Lib, mit der man die Webseite sowas wie anpingen kann und dann den anderen Prozess zu starten?
Dann ist mir (langsam erkenne ich auch etwas mehr) aufgefallen, dass die count() funktion nicht definiert ist.
Code: Alles auswählen
def main():
try:
setup()
for ring_count in count():
if DEVELOPERMODE or gpio.wait_for_edge((OPTOKOPPLER), gpio.FALLING):
record(ring_count)
wenn ich das richtig verstanden habe, ist das nicht das, was ich will, oder?
Mein Ansinnen ist, dass jedes Klingeln in einer Variable gespeichert wird und in der Message an mich als 1tes mal 2tes mal usw angezeigt wird.
Oder ersetzt diese for Schleife mein "while"?
Danke
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Montag 13. Mai 2019, 17:56
von __deets__
Lies dir doch mal die Dokumentation zu count() durch. Das beantwortet hoffentlich die Frage zur Schleife.
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Montag 13. Mai 2019, 18:05
von Sirius3
Natürlich ist `count` definiert, wird nämlich aus itertools importiert. Und was es macht, steht in der Dokumentation dazu.
Prüfen, ob der Server schon bereit ist, würde ich ja `lsof` benutzen, oder halt direkt was von psutil.
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Mittwoch 15. Mai 2019, 06:44
von Homer-S
Tut mir Leid, wenn ich hier nochmal nachfragen muss, ich steig nur nicht durch.
Was genau bedeutet diese Zeile?
for ring_count in count():
wenn ich alles, was ich gelesen habe richtig verstehe, ist count() dafür da, Anzahl Zeichen oder sowas zu zählen, bzw eine Zahlenreihe zu generieren.
Hier ist es aber ja, mehr oder weniger, None.
dann würde man sagen wiederhole für jeden ring_count in count() ...
also 0 in none??
Sorry, da bin ich echt vor einer Mauer, gedanklich.
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Mittwoch 15. Mai 2019, 07:07
von Sirius3
Was verstehst Du an der Dokumentation nicht?
Hast Du schon ausprobiert, was es tut? Das wäre das einfachste.
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Mittwoch 15. Mai 2019, 07:11
von sparrow
@Homer-S: Wenn du sagst "es aber ja, mehr oder weniger, None", meinst du dann eher 2/3 None? 1/6 None? Und was ist der Rest, wenn es nur mehr oder weniger None ist? So funktioniert Programmieren in der Regel nicht. Du musst nicht raten was das ist, du kannst es einfach ausprobieren. Sind ja nur 3 Zeilen Code itertools zu importieren, den Schleifenkopf zu schreiben und dann in der Schleife ausgeben zu lassen, was ring_count für einen Wert hat.
Wenn der Entwickler es hinterlegt hat, kommt man übrigens mit help(Objekt) an eine Hilfe im interaktiven Interpreter. Nur für den Fall, dass du die Dokumentation suchst.
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Mittwoch 15. Mai 2019, 09:28
von __deets__
Gib einfach
Code: Alles auswählen
from itertools import count
for i in count():
print(i)
ein und schau was passiert.
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Mittwoch 15. Mai 2019, 09:36
von Homer-S
sparrow hat geschrieben: Mittwoch 15. Mai 2019, 07:11
@Homer-S: Wenn du sagst "es aber ja, mehr oder weniger, None", meinst du dann eher 2/3 None? 1/6 None? Und was ist der Rest, wenn es nur mehr oder weniger None ist? So funktioniert Programmieren in der Regel nicht. Du musst nicht raten was das ist, du kannst es einfach ausprobieren. Sind ja nur 3 Zeilen Code itertools zu importieren, den Schleifenkopf zu schreiben und dann in der Schleife ausgeben zu lassen, was ring_count für einen Wert hat.
Wenn der Entwickler es hinterlegt hat, kommt man übrigens mit help(Objekt) an eine Hilfe im interaktiven Interpreter. Nur für den Fall, dass du die Dokumentation suchst.
Wenn ich mich so vorsichtig ausdrücke, liegt es daran, dass ich hier nicht Behauptungen aufstellen will die sich dann als komplett Falsch raus stellen.
Was das Resultat ist hab ich schon raus gefunden, aber WARUM funktioniert das. Das kapiere ich nicht.
Das was ich aus der Doku lese ist, dass count() etwa zählt, was in den Klammern steht. wie weiß das ding, dass es die ring_count hochzählen soll.

Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Mittwoch 15. Mai 2019, 09:46
von __blackjack__
@Homer-S: Das weiss das Ding gar nicht, das ist ihm auch völlig egal. Das liefert einfach Zahlen. Das die dann dem Namen `ring_count` zugewiesen werden, ist die Aufgabe der ``for``-Schleife. Wenn Du da ``for vorname in ['Peter', 'Paul', 'Mary']:`` schreibst, dann weiss die Liste mit den Namen ja auch nicht das die Namen an `vorname` gebunden werden. Das macht die ``for``-Schleife. Genau so weiss bei ``for i in count():` das Objekt das von `count()` erzeugt wird, nichts von dem `i`.
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Mittwoch 15. Mai 2019, 09:58
von sparrow
Homer-S hat geschrieben: Mittwoch 15. Mai 2019, 09:36Das was ich aus der Doku lese ist, dass count() etwa zählt, was in den Klammern steht. wie weiß das ding, dass es die ring_count hochzählen soll.

Aus welcher Dokumentation hast du das denn gelesen? Kannst du die mal verlinken? Das ist nämlich auf keinen Fall das, was in der Dokumentation der Funktion steht.
Und wenn du in meinen vorherigen Beitrag schaust: Da habe ich dir doch geschrieben, wie man auf eine ganz einfache Weise an Hilfe für die Funktion kommt (falls der Entwickler sie sauber im Code hinterlegt hat, was in diesem Fall so ist.)
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Mittwoch 15. Mai 2019, 10:05
von Homer-S
__blackjack__ hat geschrieben: Mittwoch 15. Mai 2019, 09:46
@Homer-S: Das weiss das Ding gar nicht, das ist ihm auch völlig egal. Das liefert einfach Zahlen. Das die dann dem Namen `ring_count` zugewiesen werden, ist die Aufgabe der ``for``-Schleife. Wenn Du da ``for vorname in ['Peter', 'Paul', 'Mary']:`` schreibst, dann weiss die Liste mit den Namen ja auch nicht das die Namen an `vorname` gebunden werden. Das macht die ``for``-Schleife. Genau so weiss bei ``for i in count():` das Objekt das von `count()` erzeugt wird, nichts von dem `i`.
Das hat geholfen!
das vorname ein .... ist die Art wie ich es kenne/verstehe. Ich konnte nicht erkennen, dass ein count() einfach bei 0 das zählen beginnt bis zum Sankt Nimmerleinstag ...
Besten Dank
Ich bin gerade in der Arbeit und kann schlecht testen. Nachdem, was ich gestern Abend mit psutil.net_connections() ausgegeben bekommen habe müsste eine einfach Abfrage den laufenden Prozess erfragen können:
Der Ausgabe Port der cam ist 9000
if '9000' in str(psutil.net_connections()):
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Mittwoch 15. Mai 2019, 10:23
von Sirius3
@Homer-S: nein, die String-Repräsentation ist nicht dafür gedacht, darin wild nach Zahlen zu suchen.
Schau Dir doch mal genau an, was diese Funktion als Rückgabewert hat, wie Du einen einzelnen Eintrag darin nach dem Port fragen kannst und baue das dann in eine Schleife ein.
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Mittwoch 15. Mai 2019, 10:55
von __blackjack__
@Homer-S: Nein, man wandelt keine Listen in Zeichenketten um um darin etwas zu suchen. Das muss in Deinem Fall a) nicht funktionieren, denn es ist nirgends garantiert wie die `repr()`-Darstellung der einzelnen Elemente in dieser Liste aussehen, und b) weisst Du doch gar nicht das die Ziffernfolge '9000' in so einer Liste sich tatsächlich auf den Port 9000 bezieht. Der Test trifft zum einen auch auf eine Portnummer 19000 zu. Zum anderen sind in der Zeichenkettendarstellung auch Prozess-IDs – eine gefundene '9000' kann also auch eine PID sein. Und selbst wenn es der Port 9000 ist – lokal oder remote? Denn es werden dort ja auch Portnummern auf der anderen Seite der Verbindung aufgelistet. Wenn also irgend ein anderer Prozess eine Verbindung zu einem anderen Rechner auf Port 9000 hat, könnte Dein Test auch positiv ausfallen.
Erst einmal brauchst Du gar nicht *alle* Verbindungen auf Deinem Rechner auflisten, denn vom `Popen()`-Objekt kannst Du die Prozess-ID von dem `mjpeg_streamer`-Prozess abfragen. Und damit dann ein `psutil.Process`-Objekt erstellen um dann nur diesen einen Prozess nach seinen Verbindungen zu fragen. Da kannst Du beim Aufruf auch schon nach TCP-Verbindungen über IPv4 filtern. Und wenn da bei den Ergebnissen dann eine Verbindung dabei ist die als lokalen Port 9000 hat und den Status `psutil.CONN_LISTEN`, dann ist der Server bereit Verbindungen anzunehmen.
Mal ein bisschen live in einer IPython-Shell mit einem Bottle-Webserver herum gespielt:
Code: Alles auswählen
In [29]: bottle = subprocess.Popen(['bottle.py', 'test'])
In [30]: Bottle v0.12.13 server starting up (using WSGIRefServer())...
Listening on http://localhost:8080/
Hit Ctrl-C to quit.
In [30]:
In [30]: bottle.pid
Out[30]: 14221
In [31]: p = psutil.Process(bottle.pid)
In [32]: p
Out[32]: psutil.Process(pid=14221, name='bottle.py', started='11:36:37')
In [33]: p.connections('tcp4')
Out[33]: [pconn(fd=3, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_S
TREAM: 1>, laddr=addr(ip='127.0.0.1', port=8080), raddr=(), status='LISTEN')]
In [34]: p.connections('tcp4')[0].laddr
Out[34]: addr(ip='127.0.0.1', port=8080)
In [35]: p.connections('tcp4')[0].laddr.port
Out[35]: 8080
In [36]: c = p.connections('tcp4')[0]
In [37]: c.laddr.port == 8080 and c.status == psutil.CONN_LISTEN
Out[37]: True
Eine Testfunktion ob ein Prozess mit einer gegebenen PID an einer gegebenen Adresse lauscht, könnte also so aussehen:
Code: Alles auswählen
def server_is_listening(pid, ip, port):
return any(
(
connection.laddr.ip == ip
and connection.laddr.port == port
and connection.status == psutil.CONN_LISTEN
)
for connection in psutil.Process(pid).connections('tcp4')
)
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Freitag 17. Mai 2019, 06:25
von Homer-S
Damit komm ich gerade nicht weiter.
Code: Alles auswählen
for connection in psutil.Process(pid).connections('tcp4')
den Befehl gibt es so nicht. Wenn ich das Process(pid) weg lasse, geht es zwar weiter, aber das ist glaub ich nicht was wir wollen ...
die Doku sagt auch nur von den kinds wie tcp4. auf ein pid kann ich dort in der Klammer nicht eingrenzen ...
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Freitag 17. Mai 2019, 07:13
von __blackjack__
@Homer-S: Da muss die PID von dem Prozess rein, von dem man die Verbindungen haben will. Schau doch mal in dem Code-Block davor wo ich die für den Bottle-Prozess her habe.
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Freitag 17. Mai 2019, 08:41
von Homer-S
__blackjack__ hat geschrieben: Freitag 17. Mai 2019, 07:13
@Homer-S: Da muss die PID von dem Prozess rein, von dem man die Verbindungen haben will. Schau doch mal in dem Code-Block davor wo ich die für den Bottle-Prozess her habe.
Hab ich drin mit pid = video.pid
wird auch korrekt ausgegeben. hatte ich vergessen mit anzugeben.
Es wirft mir trotzdem einen Fehler raus, Process kein connections kennt ...
Mein zweiter Ansatz war psutil.net_connections zu nutzen, da ich die pid ja habe, aber da kann ich (vielleicht nur ich

nicht die Einschränkung/Filter pid setzen. Der kennt nur die kind's ....
Re: DIY Klingel für Haus programmieren - Robustheit
Verfasst: Freitag 17. Mai 2019, 12:03
von __blackjack__
@Homer-S: `pid` ist keine Einschränkung oder ein Filter sondern das Argument was man halt braucht um ein `psutil.Process`-Objekt zu erstellen. Und die `connections()`-Methode gibt es auf den Objekten auch mindestens seit 2013, davor hiess sie `get_connections()`. Wie alt ist denn Dein `psutil`‽