Probeme bei PHP->XML->Python

  • Hallo zusammen,

    ich habe auf meinem Pi jetzt einen Webserver laufen der per PHP eine XML-Datei beschreibt. Diese wird von einem Python Script ausgewertet, das klappt nur so halb.
    Also PHP kann die XML-Datei bearbeiten und Python kann diese Lesen nur, wenn das Python Script läuft und die XML-Datei sich ändert, bekomme ich folgende Fehlermeldung:

    Meine erste Idee wäre es jetzt im Python Script zu gucken, ob die Datei geändert wurde und wenn ja einlesen.
    Jetzt habe ich erst mal drei Fragen:

    1. Kann das Funktionieren?
    2. Wie wird so was umgesetzt?
    3. Gibt es bessere Möglichkeiten?

    Danke für eure mühen.

  • Wie sieht denn dein Python Script aus?

    Du könntest die "last modification time" der XML Datei überwachen, die Datei dann parsen und die gewünschten Sachen in ein Array hinterlegen. Dann geht das Script wieder zuück in den 'Überwachungsmodus'

    Aber mal so am Rande gefragt: Wozu das alles? Also was wird durch PHP in die XML Datei geschrieben und was soll das Python Script dann damit machen? Evtl. gibts da ne bessere Lösung ;)

  • Ich hab mal alles auch mit Webserver hier dran gehangen.

    Eigentlich geht es nur darum eine LED-Strip via Browser zu steuern. Ich habe mich bewusst für diesen Weg entschieden, denn es ging für mich eher darum zu gucken ob ich es ans Laufen bekommen.

    Und das mit der "last modification time" werde ich mir mal angucken.
    Danke

    Edit:

    Ich hab jetzt mal das hier mit aufgenommen:

    Leider bekomme ich jetzt die Fehlermeldnung:

    Code
    pi@raspberrypi ~ $ sudo python3 /home/pi/Documents/testalles.py
      File "/home/pi/Documents/testalles.py", line 27
        return (t)
                 ^
    IndentationError: unindent does not match any outer indentation level

    jemand eine Idee?

  • Hm, ohne die Dateien jetzt gesehen zu haben könntest du diese Steuerung auch über Sockets realisieren, indem das Python Script auf einem bestimmten Port lauscht, das PHP Script (bzw Javascript) dort hin dann verbindet und einen entsprechenden Befehl absetzt.

    Auch könntest du das einfach über eine normale text Datei realisieren - was dann aber aufs ähnliche wie mit der XML Datei hinaus laufen würde. Du übergibst ja nur die PWM Werte für RGB, das kann man auch einfach in eine Textdatei schreiben lassen, ohne dieses XML Konstrukt drum herum.

    Aber wie gesagt glaube ich wäre Sockets besser und auch schneller/direkter.


    Auf den ersten Blick in deine dimmer.php glaub ich dass das ein wenig zu starr geschrieben ist. Beim _GET kannst du den gewünschten Wert eigentlich gleich mit übergeben und brauchst dann eigentlich auch kein switch

    Die testalles.py wird vermutlich auch ziemlich hohe CPU Last erzeugen, kann das sein? Da die ja ungebremst durch die while immer und immer wieder die xml ausliest...

    Dein Script könntest du zum Beispiel wie folgt verändern:

    [code=php]
    #!/usr/bin/python3.2
    # -*- coding: UTF-8 -*-

    # Alle Libs inportieren
    import os
    from lxml import etree

    # Konfiguration
    inFile = '/var/www/Dim.xml' # XML-Datei


    def main():
    while True:
    if os.path.isfile(inFile):
    lastTime = os.path.getmtime(inFile)
    if os.path.getmtime(inFile) <> lastTime:

    # XML-Datei einlesen
    xmlData = etree.parse(inFile)
    messages = xmlData.findall("Dimmer")

    # Werte aus XML-Datei extrahieren
    for msgGreen in messages:
    Green_value = msgGreen.findtext("Green_value")

    for msgRed in messages:
    Red_value = msgRed.findtext("Red_value")

    for msgBlue in messages:
    Blue_value = msgBlue.findtext("Blue_value")

    print(Green_value)
    print(Red_value)
    print(Blue_value)

    if __name__ == '__main__':
    main()
    [/php]

    dadurch wird aber auch eine CPU Last von ca. 100% auf einem quadcore Pi2 verursacht. Es sollte also zumindest ein time.sleep(0.5) oder etwas höher in der while eingebaut werden.

  • Ich kann den Fehler auf der Seite von Python nicht reproduzieren. Aber dennoch würde ich ``os.chdir('..')`` weglassen und stattdessen einen Pfad angeben. Auch rattert deine endlos-Schleife im Nanosekundentakt runter. Ein ``time.sleep(x)`` würden dem RPi gut tun. Warum bei dir der Fehler kommt, dass die Datei leer sei, kann ich nicht sagen. Ich kenne mich mit php nicht aus und das ist auch gut so ;)

    Edit:
    meigrafd war schneller i.S. time.sleep
    Kann es sein, dass dein php Skript die Datei immer wieder neu schreibt und da deine endlos-Schleife auf hochtouren läuft, wird halt gleich mal ne leere Datei geparst

    Edit II:
    dies wird bei dir wohl der Fall sein. Also musst du den Fehler abfangen um das Programm am Leben zu erhalten...

  • Danke für eure Hilfe..

    Ich habe es jetzt soweit am laufen.
    Hinzu gekommen ist noch das Steuern auf feste Werte.Mein Skript:
    [code=php]#!/usr/bin/env python3
    # -*- coding: UTF-8 -*-

    # Alle Libs inportieren
    import os
    from lxml import etree
    import time
    import shutil
    import RPi.GPIO as GPIO

    # Konfiguration
    inFile = "/var/www/data/com.xml" # XML-Datei
    Green_Pin = 20
    Red_Pin = 21
    Blue_Pin = 16

    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(Green_Pin, GPIO.OUT)
    GPIO.setup(Red_Pin, GPIO.OUT)
    GPIO.setup(Blue_Pin, GPIO.OUT)
    GreenLed = GPIO.PWM(Green_Pin,100)
    RedLed = GPIO.PWM(Red_Pin,100)
    BlueLed = GPIO.PWM(Blue_Pin,100)

    def fadeValue(color, a, b, c):
    if a == b:
    print("No action is requird for ", color)

    elif a < b:
    #print(color, "add 1 to ", a)
    a = a + 1

    elif a > b:
    #print(color, "deduct 1 from ", a)
    a = a - 1
    c.ChangeDutyCycle(a)
    return a

    def writeValue(color, a, b):
    b.ChangeDutyCycle(a)
    #print(color, "set to", a)
    return a

    def readXML(a, Text):
    for b in a:
    c = b.findtext(Text)
    return c

    def setup():
    shutil.copy('/var/www/data/com_Org.xml', inFile)
    GreenLed.start(0)
    RedLed.start(0)
    BlueLed.start(0)


    def main():
    Green_ActualValue = float(0)
    Red_ActualValue = float(0)
    Blue_ActualValue = float(0)

    while True:
    if os.path.isfile(inFile):

    # XML-Datei einlesen
    xmlData = etree.parse(inFile)
    messages = xmlData.findall("Dimmer")

    Fade_Mode = readXML(messages, "Fade_mode")
    Green_setpoint = float(readXML(messages, "Green_value"))
    Red_setpoint = float(readXML(messages, "Red_value"))
    Blue_setpoint = float(readXML(messages, "Blue_value"))

    if Fade_Mode == "fade":
    Green_ActualValue = fadeValue("Green", Green_ActualValue, Green_setpoint, GreenLed)
    Red_ActualValue = fadeValue("Red", Red_ActualValue, Red_setpoint, RedLed)
    Blue_ActualValue = fadeValue("Blue", Blue_ActualValue, Blue_setpoint, BlueLed)
    time.sleep(0.25)

    elif Fade_Mode == "write":
    Green_ActualValue = writeValue("Green", Green_setpoint, GreenLed)
    Red_ActualValue = writeValue("Red", Red_setpoint, RedLed)
    Blue_ActualValue = writeValue("Blue", Blue_setpoint, BlueLed)
    time.sleep(0.5)

    else:
    time.sleep(0.5)

    if __name__ == '__main__':
    setup()
    main() [/php]

    Ich habe aber immer noch 2 Probleme.
    1. Die rote LED ist wesentlich dunkler als die anderen. Das wird aber mit der LED-Strip zusammen hängen. Die Widerstände sind bereits auf der Strip verlötet.
    2. Wenn ich die LEDs in einem Bereich bis ca. 40% ansteuer, Flackern diese sporadisch. Kann das was mit der RPi.GPIO Bibliothek zu tun haben? oder habe ich einen Fehler im Code?:danke_ATDE:

  • Ich hab den hier noch mal aufgemacht...

    Und zwar geht es immernoch um das auslesen einer XML-Datei. Und zwar würde ich gerne erst : /root/alarm[0]/aktiv auslesen und dan /root/alarm[1]/aktiv. Also beim ersten würde ich das Ergebnis "true" erwarten und beim zweite das Ergebnis "false".

    Wenn das was in dem Python Skript steht richtig verstanden habe ist es volgender Ablauf:
    1. die Datei wird geparst xmlData = etree.parse(inFile)
    2. Erstellen einer Liste mit den Adressen aller gefundenen alarm Tags messages = xmlData.findall("alarm")
    3. Inerhalb von alarm nach dem Tag "aktiv" suchen und dessen wert Ausgeben Wert = readXML(messages, "aktiv")
    4. Als Wert bekomme ich "false".

    Also liest der den zweiten alarm aus.

    Meine Idee war es nun da messeges eine Liste enthält mit einem Index zu arbeiten. Also habe ich die Zeile so geändert Wert = readXML(messages[0], "aktiv") um den ersten alarm zu erhalten.

    Leider geht das nicht.
    Als antwort erhalte ich dann:

    Code
    Ausgabe von  /var/www/data/alarmClock.xml
    findall alarm  [<Element alarm at 0x1ca3ad0>, <Element alarm at 0x1ca3af8>, <Element alarm at 0x1ca3b20>, <Element alarm at 0x1ca3b48>, <Element alarm at 0x1ca3b70>, <Element alarm at 0x1ca3b98>, <Element alarm at 0x1ca3bc0>]
    messages ist vom Typ <class 'list'>
    Ausgabe von  /var/www/data/alarmClock.xml
    readXML mode  None
    Wert ist vom Typ <class 'NoneType'>


    Die XML-Datei:

    Das Python Skript:
    [code=php]#!/usr/bin/env python3
    # -*- coding: UTF-8 -*-

    from lxml import etree
    import time

    def readXML(a, Text):
    for b in a:
    c = b.findtext(Text)
    return c

    # Konfiguration
    inFile = "/var/www/data/alarmClock.xml" # XML-Datei
    # XML-Datei einlesen
    xmlData = etree.parse(inFile)

    messages = xmlData.findall("alarm")
    print("Ausgabe von ", inFile)
    print("findall alarm ", messages)
    print("messages ist vom Typ", type(messages))

    Wert = readXML(messages, "aktiv")
    print("Ausgabe von ", inFile)
    print("readXML mode ", Wert)
    print("Wert ist vom Typ", type(Wert))[/php]

    Ich habe da wohl was Falsch verstanden... Kann mich da mal einer aufklären?
    Vielen Dank.

    kurze Frage zum Forum:
    Habe jetzt öffters gesehen das mann mittels Spoiler Code ausblenden kann. Wie geht das?

  • Lösung gefunden.

    Ich hatte nur nen Blöden Denkfehler drin. messages darf nicht mit einem Index aufgerufen werden. Jetzt erhalte ich eine Liste mit allen Werten für einen Tag.
    So geht es jetzt:
    [code=php]#!/usr/bin/env python3
    # -*- coding: UTF-8 -*-

    from lxml import etree
    import time

    def readXML(messages, Text):
    Wert = []
    for alarm in messages:
    Wert.append(alarm.findtext(Text))
    return Wert

    # Konfiguration
    inFile = "/var/www/data/alarmClock.xml" # XML-Datei
    # XML-Datei einlesen
    xmlData = etree.parse(inFile)

    messages = xmlData.findall("alarm")
    print("Ausgabe von ", inFile)
    print("findall alarm ", messages)
    print("messages ist vom Typ", type(messages))

    Wert = readXML(messages, 'aktiv')
    print("Ausgabe von ", inFile)
    print("readXML mode ", Wert)
    print("Wert ist vom Typ", type(Wert))[/php]

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!