Fragen zur Performace bei externen Abfragen

Begonnen von Fistandantilus, 29 Dezember 2015, 02:40:02

Vorheriges Thema - Nächstes Thema

Fistandantilus

Hallo,

ich bin gerade dabei meine Haussteuerung per FHEM umzusetzen. Das Ganze läuft auf einem Raspberry2. Für den Teil der Alarmanlage kommt ein zweiter Raspberry zum Einsatz, an dem ein rfid Reader und ein Display für Statusanzeigen angeschlossen sind, sowie die Sirene. Die Sicherheitsrelevanten Komponenten frage ich vom FHEM per http request ab. Das sind Status Alarmanlage (on/off) und Alarmstatus (on/off).
Status Alarmanlage wird bei jedem 10. Durchlauf des Scriptes gelesen, Alarmstatus nur bei Status Alarmanalge on und dann auch nur bei jedem 10. Durchlauf. Das ist somit im Schnitt 1 Request alle 1,5 Sekunden. Ist das zuviel? Sollte ich den Durchläuf verlängern? Hat jemand einen ähnlichen Anwendungsfall?
Alternativ wäre noch die Möglichkeit den Status direkt aus der Datenbank abzurufen.

VG
F.
Raspberry Pi 3 + FHEM + Smartvisu/Fronthem, CUL, HMLAN, Enocean USB300, Eltako (FAM14, FSB14, FSR,FTS14EM,Multisensor,...) - MySQL DB + 2.Raspberry für Heizungsregelung und 3. Raspberry als Alarmanlage

dev0

Das sind zu wenig Details um die Frage ordentlich beantworten zu können. Auf den ersten Eindruck wirkt das Konstrukt "Schleife bei jedem 10 mal..." etwas schräg. Ich würde den 2. Pi nicht pollen, sondern ihn sofort aktiv an den 1. Pi aktiv reporten lassen, wenn der Status nicht ok ist oder ein Alarm ausgelöst wurde. Zusätzlich jede Minute einen keepalive mit status, dass alles ok ist.

Fistandantilus

Auf dem Anzeige-Pi läuft ein Python-Script, deshalb das "schräge" Konstrukt. Ich muss ja den RFID Reader permanent abfragen. Den Status dahin zu melden wird denke ich so nicht funktionieren. Außer ich stecke erheblichen Aufwand in die Programmierung. Das Display wird über gpio angesteuert.
Raspberry Pi 3 + FHEM + Smartvisu/Fronthem, CUL, HMLAN, Enocean USB300, Eltako (FAM14, FSB14, FSR,FTS14EM,Multisensor,...) - MySQL DB + 2.Raspberry für Heizungsregelung und 3. Raspberry als Alarmanlage

dev0

Zitat von: Fistandantilus am 29 Dezember 2015, 08:31:45
Außer ich stecke erheblichen Aufwand in die Programmierung
Wo ist der Aufwand im Alarmfall vom Script eine http/telnet url aufzurufen zu lassen oder 1x in der Minute den Status zu pushen?
Alle 1.5s zu pollen ist ein schlechtes Design und würde ich nicht machen, egal ob Datenbank oder sonst wie.
Ansonsten, wie schon geschieben: Ohne Details wirst Du auch keine andere brauchbare Antwort bekommen.

viegener

Wie bereits gesagt, polling ist hierbei sicher nicht die beste Lösung und generisch zu sagen, ob es "zuviele" Requests sind ist schon gar nicht möglich. Wichtig ist aber dass Aufrufe wie http-Requests als non-blockingrequests (also über HTTPMOD) abgewickelt werden, sonst ist u.U. jeder HTTP-Request zuviel, da das ganz FHEM sonst auf das Ende des Requests warten muss (inkl. möglicher timeouts bei Nichterrecihbarkeit).



Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

Fistandantilus

#5
Danke für Euren Input hier noch ein paar mehr Details. Auf dem ersten Raspi läuft FHEM mit DBLog und Smartvisu als Frontend.
Der zweite Raspi hat nur das Raspian drauf und Python als Scriptsprache. Es ist ein C-Berry Display über gpio angeschlossen, sowie ein RFID Reader. Im Alarmfall wird per gpio noch ein Relais geschaltet für die 12V der Sirene.

Das Main Script sieht aktuell etwa so aus:

try:
    while True:
        previus_hour = hour
        curr_time = datetime.datetime.now()
        hour = curr_time.strftime("%H")
        #hour = zeit()

        #even if hour = allowed hour, only run once in that hour
        if (previus_hour == hour):
            do_not_run = 1
        else:
            do_not_run = 0
   
        #get weather forecast only 3 times a day as weather.com has a limit of 10000 requests per month
        if ((wetter == "" or hour == 8 or hour == 16 or hour == 24) and do_not_run == 0):
            wetter = getweather()
            do_not_run = 1
       
        if readcounter1 == 0:
            status = systemstatus_get()
            readcounter1 = readcounter1 + 1
            logging.debug('System-Status:' + str(status))
        else:
            readcounter1 = readcounter1 + 1
           
        if readcounter1 == 10:
            readcounter1 = 0
       
        #logging.debug('System-Status:' + str(status))
        if (status == "on" and readcounter2 == 0):
            alert = alert_get()
            readcounter2 = readcounter2 + 1
            logging.debug('Alarm-Status:' + alert)
        elif (status == "on" and readcounter2 <> 0):
            readcounter2 = readcounter2 + 1
           
        if readcounter2 == 10:
            readcounter2 = 0
       
        #logging.debug('System-Status:' + status)
        if (status == "on" and alert == "off"):
            statusicon = "status_on48.png"
            armedscreen()
        elif (status == "on" and alert == "on"):
            statusicon = "status_on48.png"
            alertscreen()
            #logging.debug('ALERT')
            # do just once
            if (alarmcounter == "0"):
                subject = "Sicherheitsbruch"
                content = "Achtung, es wurde ein Sicherheitsbruch festgestellt."
                sendmail(subject,content)
                alarmcounter = "1"
        else :
            statusicon = "status_off48.png"
            alarmcounter = "0"
            offscreen(wetter, statusicon, alert)
           
        #logging.debug('ICON:' + statusicon)
       
        for i in range(1):
            #ID = rfid()
            ID = '1234'
            #logging.debug('ID:' + ID)
       
        #logging.debug('OK')
       
        if ID in userdict:
            #Key recognized, current armed status: " + str(status)
            #logging.debug('Hello User:' + userdict[ID])
            sound(userdict[ID])
           
            if (status == "on"):
                systemstatus_set_off()
                #logging.debug('sending off command to fhem')
                sound("disarmed")
            else:
                systemstatus_set_on()
                #logging.debug('sending on command to fhem')
                sound("armed")
        else:
            logging.debug('key not recognized')
               
except KeyboardInterrupt:
    switchscreen()
    GPIO.cleanup()


Die http requests sehen so aus:
urllib2.urlopen('http://192.168.1.39:8083/fhem&cmd=%7BValue%28%22Securasp_Alarm%22%29%7D&XHR=1')

Wenn man das Ganze besser gestalten kann, bin ich für Hilfe dankbar. Httpmod schau ich mir mal an. Wie ich das Ganze von FHEM aus trigger, erschließt sich mir aktuell noch nicht, dazu müsste doch auf dem Anzeige Raspi ein Websocket laufen. Momentan hab ich nur noch die Adafruit WebIDE für Python drauf.
Raspberry Pi 3 + FHEM + Smartvisu/Fronthem, CUL, HMLAN, Enocean USB300, Eltako (FAM14, FSB14, FSR,FTS14EM,Multisensor,...) - MySQL DB + 2.Raspberry für Heizungsregelung und 3. Raspberry als Alarmanlage

viegener

Zitat von: Fistandantilus am 29 Dezember 2015, 13:07:40

Die http requests sehen so aus:
urllib2.urlopen('http://192.168.1.39:8083/fhem&cmd=%7BValue%28%22Securasp_Alarm%22%29%7D&XHR=1')

Wenn man das Ganze besser gestalten kann, bin ich für Hilfe dankbar. Httpmod schau ich mir mal an. Wie ich das Ganze von FHEM aus trigger, erschließt sich mir aktuell noch nicht, dazu müsste doch auf dem Anzeige Raspi ein Websocket laufen. Momentan hab ich nur noch die Adafruit WebIDE für Python drauf.

Dann habe ich das missverstanden. Du machst ja einen poll vom NICHT-FHEM-Rechner auf FHEM per http (ich hatte es umgekehrt interpretiert).
Auf dem NICHT-FHEM-Rechner läuft eine Statusanzeige und es ist das Alarmrelais angeschlossen, korrekt?

Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

Fistandantilus

Raspberry Pi 3 + FHEM + Smartvisu/Fronthem, CUL, HMLAN, Enocean USB300, Eltako (FAM14, FSB14, FSR,FTS14EM,Multisensor,...) - MySQL DB + 2.Raspberry für Heizungsregelung und 3. Raspberry als Alarmanlage

CoolTux

Mir erschließt sich noch nicht das gesamte Konzept. Insbesondere die Aufgabe von FHEM. Sollen nur Zustände dargestellt werden? Soll auf Zustände seitens FHEM reagiert werden?

Ich würde Daten an FHEM nur bei Zustandsänderung senden. Ansonsten ist das unnützer Datenverkehr.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

viegener

Dann sollte normalerweise ein Request alle 1.5sec noch ok sein, aber klar ist, dass ein push hier natürlich besser ist, wenn Du nicht alle 3 Sec einen Alarm hast  ;D

Eine Alternative könnte ein sogenannter long poll sein, bei dem die Anfrage erst beendet wird, wenn sich etwas ändert. Das erfordert aber ein grundsätzlich anderes Vorgehen auf dem NICHT-FHem-Server. Da die Anfrage "im Hintergrund läuft". Für das Status-UI wäre das die übliche Vorgehensweise, denn die meisten UIs verwenden long poll zum updaten der Anzeige.
Für die Sirene wäre ein direkter Push eigentlich besser.



Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

Fistandantilus

Von der Funktionsweise her läuft es wie folgt:

- In FHEM gibt es ein Dummy Device für die Alarmanlage, so kann ich sie ggf. auch von extern (VPN) einschalten/deaktivieren
- die Fensterkontakte und später noch 1-2 Bewegungsmelder werden ebenfalls in FHEM geführt
- wenn das Dummy Device on ist, wird bei Statusänderung der Fensterkontakte/Bewegungsmelder in FHEM der Alarmstatus gesetzt
- im 2. Raspi frage ich nur ab, ob die Anlage on ist und ob bei on der Alarmstatus gesetzt ist
- in FHEM setze ich bei gültigem RFID Scan die Alarmanlage auf on oder off

Der Datenverkehr zwischen Raspi2 und FHEM beschränkt sich also nur auf die Abfrage on/off für die Anlage und falls on noch zusätzlich auf den Alarmstatus. Das Python Script benötigt für einen Durchlauf zwischen 0,1 und 0,2 Sekunden für die Logik und die Anzeige zusätzlicher Informationen (z.B. Wetter) auf dem Display. Ich lasse aktuell nur bei jedem 10. Durchlauf FHEM abfragen, um den Traffic noch weiter zu reduzieren.
Damit die Anzeige auf dem 2. Raspi bei erfolgreichen RFID Scan auch direkt den richtigen Status anzeigt, ist ein größeres Intervall ungünstig.

Grundsätzlich habt Ihr natürlich recht, das ein Push vom FHEM rein für die Statusänderung günstiger wäre, aber rein von der Umsetzung (websocket, webserver) wäre das denke ich um einiges aufwendiger und ressourcenlastiger auf Raspi2 Seite.
Raspberry Pi 3 + FHEM + Smartvisu/Fronthem, CUL, HMLAN, Enocean USB300, Eltako (FAM14, FSB14, FSR,FTS14EM,Multisensor,...) - MySQL DB + 2.Raspberry für Heizungsregelung und 3. Raspberry als Alarmanlage

viegener

Das verstehe ich, deshalb der Vorschlag mit dem longpoll, das ist wie push aber ohne push  ;)

Kein Support über PM - Anfragen gerne im Forum - Damit auch andere profitieren und helfen können

Fistandantilus

Das muss ich mir mal anschauen, da der http request ja aktuell nicht über einen Browser oder Socket läuft. Da muss ich mir erstmal die Implementierung anschauen, da ich mit Python bisher noch ziemlich wenig gemacht habe.
Raspberry Pi 3 + FHEM + Smartvisu/Fronthem, CUL, HMLAN, Enocean USB300, Eltako (FAM14, FSB14, FSR,FTS14EM,Multisensor,...) - MySQL DB + 2.Raspberry für Heizungsregelung und 3. Raspberry als Alarmanlage