Zwei Scripte sollen interagieren

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
oiskipoiski
User
Beiträge: 5
Registriert: Dienstag 25. Mai 2021, 07:58

Hallo, ich bin neu hier. Ich bin kein Programmierer, bitte berücksichtigt das bei euren Antworten, danke.

zu meinem Problem:
Ich habe mir einen Türöffner mit RFID Leser gebastelt. Funktioniert auch wunderbar. Wenn ich eine gültige Karte einlese wird ein Script gestartet, dass einen Motor steuert der den Schlüssel im Schloss dreht.
Das funktioniert aber nur für das Aufschließen. Zusperren geht nur über die App SSH-Button.
Nun habe ich mir überlegt, zusätzlich noch einen Touch-Sensor mit einzubeziehen. Wenn der Touchsensor berührt wird soll eine Variable (touch) von 0 auf 1 gesetzt werden und diesen Wert für 5 Sekunden halten.
Das Türöffnerscript soll nun auf diesen Wert zugreifen und so lange dieser "1" ist die Tür zusperren und bei Wert "0" aufsperren.
So wie ich es jetzt probiert habe funktioniert es nicht. Ich lasse das Script "touch.py" laufen und starte danach "Read.py". Read.py liest jetzt nicht mehr de Chip aus sondern macht das gleiche wie touch.py: Wenn ich den Sensor berühre wird der Wert von "touch" ausgegeben (1) und 5 Sekunden später die "0". Mehr nicht.

Hier die beiden Scripte.
Zuerst touch.py:

Code: Alles auswählen

#!/usr/bin/env python3
#tweaked a script from an adafruit tutorial
#https://learn.adafruit.com/playing-sounds-and-using-buttons-with-raspberry-pi?view=all


import os
from time import sleep
import RPi.GPIO as GPIO

touch = 0

GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.IN,pull_up_down=GPIO.PUD_UP)



while True:

    try:

        if (GPIO.input(4) == True):
            touch = 1
            print(touch)
            sleep(5)
            touch = 0
            print(touch)

    except KeybordInterrupt:
        GPIO.cleanup()


    sleep(0.5);

und dann Read.py: (Der Teil um den es geht steht zwischen "++++++++Meincode++++++" und "++++++++++Ende Mein Code+++++")

Code: Alles auswählen

#!/usr/bin/env python3

import RPi.GPIO as GPIO
import subprocess
from pirc522 import RFID
from time import sleep
from touch.py import touch
rdr = RFID()



while True:


    rdr.wait_for_tag()
    (error, tag_type) = rdr.request()
    if not error:
        print ("Karte gefunden")
        (error, uid) = rdr.anticoll()
    if not error:
#        print("UID: " + str(uid))
# Select Tag is required before Auth
        if not rdr.select_tag(uid):
# Auth for block 10 (block 2 of sector 2) using default shipping key A
           if not rdr.card_auth(rdr.auth_a, 10, [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], uid):
# This will print something like (False, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
#             print("Reading block 8: " + str(rdr.read(8)))


# ++++++++++++++Mein Code+++++++++++++++++++++++
                   gelesen = str(rdr.read(8))
                   richtigeid = "(False, [83, 101, 115, 97, 109, 111, 101, 102, 102, 110, 101, 100, 105, 99, 104, 32])"

#                   print("Variable test: "+test)
#                    print("richtige ID: "+richtigeid)
                   if gelesen == richtigeid and touch == 1:
                        print("Richtige Karte - zuschliessen")
                        print(touch)
#                        subprocess.Popen("/home/pi/Motor/zu.py")
                   elif gelesen == richtigeid and touch == 0:
                        print("richtige Karte - aufschliessen")
#                        subprocess.Popen("/home/pi/Motor/auf.py")
                   else:
                       print("falsche Karte")
                   sleep(1)


# ++++++++++++++Ende Mein Code++++++++++++++++++

# Always stop crypto1 when done working
    rdr.stop_crypto()
    
Ich gehe mal stark davon aus, dass es in erster Linie meine Methode ist die Variable "touch" zu importieren.
Ich hab im Netz gelesen, dass man so etwas besser mit Threads und Funktionen macht, aber nicht verstanden wie es gemacht wird. Da fehlen mir wohl einfach die Programmierkenntnisse. Kann mir bitte jemand weiterhelfen?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Frage ist erst einmal, ob Du soweit programmieren lernen willst, dass Du das Problem selbst lösen kannst, oder erwartest, dass hier jemand umsonst Dein Programm so anpasst, wie Du es wünschst?

Das `as` bei `import` ist zum Umbenennen da, GPIO wird aber gar nicht umbenannt. GPIO.cleanup sollte immer aufgerufen werden, nicht nur bei Strg+C.
Sowohl die Klammern bei der if-Bedingung als auch das == True sind überflüssig.

Das # bei Kommentare sollten immer soweit eingerückt werden, dass es mit dem umgebenden Block übereinstimmt, sonst ist der Code unlesbar, wie bei Dir. Eingerückt wird immer mit 4 Leerzeichen pro Ebene, und nicht mal 4 und mal 5.

Das einfachste ist, wenn Du für Deinen Sensor mit `add_event_detect` einen Callback installierst, der Dir bei steigender Flanke den aktuellen Timestamp in eine Queue schreibt und Du diese Queue dann im RFID-Code abfragst, und prüfst, ob ein Timestamp existiert und dieser weniger als 5 Sekunden in der Vergangenheit liegt.
oiskipoiski
User
Beiträge: 5
Registriert: Dienstag 25. Mai 2021, 07:58

Hallo,
danke erstmal für die Antwort.

Ich habe es in der Zwischenzeit tatsächlich selbst hinbekommen.
Dass ich das so nicht mit einem import machen kann habe ich erkannt.
Gelöst habe ich das Ganze mit datei.write und datei.read. Das Touchscript schreibt den jeweiligen Zustand als "0" bzw. "1" in eine Datei und das RFID Script liest diesen Wert aus der Datei wieder aus.
Funktioniert.
Aber was ich auf jeden Fall beherzigen und machen werde ist die Geschichte mit den Einrückungen. Das ist mir selbst schon aufgestoßen.
Das mit dem GPIO.cleanup wäre meine nächste Baustelle. Da will ich noch ein except KeyboardInterrupt einbauen. Mittlerweile habe ich schonmal gelernt, dass da ein "try:" dazu gehört. Aber das bekomme ich bestimmt dann auch noch raus.

Danke, fürs erste wars das von mir auch schon.
roland51
User
Beiträge: 7
Registriert: Freitag 21. Mai 2021, 16:06

Hallo,

Ich finde das gesamte Konzept etwas verwirrend !

Ohne jetzt groß in das Konzept des Threadings einzugehen, würde ich den Weg des geringsten Widerstands gehen. Auch und möglicher Weise, dass Python Profis hier anderes vorgehen würden.

Mache dir einen Programmablaufplan, der dem gesamten Funktionsablauf widerspiegelt.

Ich würde damit beginnen.
Endlosschleife
Warte bis eine RFID Karte identfiziert wurde
Überprüfe, oder der Zugangscode gültig ist
Verzweigung
Wird eine Sensor bedient, dass die Türklinke oder was auch immer angefasst wurde -> Dann schließe auf
& Starte einen Thread der nur eine Verweilzeit enthält
# Wenn die Tür keinen Sensor hat das sie wieder geschlossen ist, wird es schwierig, denn ... selber mal nachdenken
# Wenn die Tür oder das Schloss auf Schliessen geht, bevor diese wirklich geschlossen ist, dann steht diese möglicher Weise
# ständig offen
ist die Tür nach der Verweilzeit des Threads ( geht über Variablen die mit GLOBAL bedient werden ) wieder zugefallen, dann schließe
/ wieder ab

Wenn man das schnelle "Aufschließen" mit einem Sensor an der Türe / Türklinke macht, dann muss man auch sicherstellen, dass jemand die Tür aus der Grundposition bewegt hat, denn sonst wird das nichts ! Ist die Tür noch halboffen, oder jemand hat sie am Schließen gehindert, schließt das Schloss, und der Schloßmechanimus verhindert, dass die Tür wirklich ins Schloss fällt
...
Ich weiss, dass ist etwas Theoretisch ! Aber einen Ablauf sollte man, wenn alle Komponenten und Fehlerquellen erfasst sind genau planen , bevor man sich an einen Lösungsansatz setzt.

Grüße
Roland
oiskipoiski
User
Beiträge: 5
Registriert: Dienstag 25. Mai 2021, 07:58

roland51 hat geschrieben: Dienstag 25. Mai 2021, 20:55 Hallo,

Ich finde das gesamte Konzept etwas verwirrend !
Möglicherweise gehst du einfach von anderen Voraussetzungen aus als ich. Ich kläre mal auf:
Die Tür hat zwei Arten von "zu" einmal das ins Schloss gefallen, oder zu durch Schnappriegel und das richtige zu, also das zuschließen mit Sperrriegel. Sprich eine ganze normale Eingangstür.
Von innen ganz klar mit der Klinke zu bedienen, von außen eigentlich nur mit Schlüssel im Schloß. Und hier komme ich :mrgreen: !
Um mir das mit dem Schlüssel zu sparen habe ich bereit seit mehreren Jahren einen RFID Leser mit Motorbetriebenen Öffnungsmechanismus (innen angebracht) in Betrieb. Abschließen war auch möglich, aber eben nur über das direkte Aufrufen des entspr. Scripts und nicht über den RFID Leser. Und genau diesen Zustand habe ich nun -erfolgreich- geändert so dass ich jetzt auch mit meiner Schlüsselkarte die Türe zusperren kann, nämlich durch das vorherige betätigen eines Touchschlters/-sensors der die "Aufschliessautomatik" für einen kurzen fest definierten Zeitraum auf Verschließen stellt.

Auf deine weiteren Punkte gehe ich jetzt nicht im einzelnen ein, da sie an meinem eigentlichen, jetzt bereits gelösten, Problem vorbeigehen. Aber danke für die Vorschläge.
Antworten