Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. Python3 Skript in Iobroker einbinden

NEWS

  • Jahresrückblick 2025 – unser neuer Blogbeitrag ist online! ✨
    BluefoxB
    Bluefox
    17
    1
    2.5k

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    13
    1
    993

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    25
    1
    2.3k

Python3 Skript in Iobroker einbinden

Geplant Angeheftet Gesperrt Verschoben JavaScript
30 Beiträge 3 Kommentatoren 3.9k Aufrufe 2 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • rrov1R rrov1

    @fibs Hallo,

    ioBroker und Eingabeaufforderung passt in meinen Gedanken grad nicht zusammen. Der ioBroker werkelt im Hintergrund man benutzt eine Webseite auf einem abgesetzten Gerät mit dem man ein Visualisierung aufruft. An die Eingabeaufforderung auf dem ioBroker kommt keiner ran.

    Wenn ich das benötigen würden, dann würde ich:

    • 3 Datenpunkte anlegen in denen ich die 3 Werte die du per input() in dem Pyhton Skript abfragst halten kann.
    • Eine Visualisierung bauen (z.B. vis) mit der ich die 3 Werte setzen/ändern kann
    • Die 3 Werte aus den Datenpunkten dem Python Skript mitgeben als Parameter.

    Für den letzten Schritt hier mal (ungetestet) noch die angepassten Skripte:
    Javascript:

    on({id: "pfad.0.zum.datenpunkt", change: "any"}, function (obj) {
        var Spielfeldlaenge = getState("pfad.zur.Spielfeldlaenge").val;
        var Spielfeldbreite = getState("pfad.zur.Spielfeldbreite").val;
        var Torlänge = getState("pfad.zur.Torlänge").val;
        exec('python3 /pfad/zum/script.py ' + Spielfeldlaenge + ' ' + Spielfeldbreite + ' ' + Torlänge, function (error, stdout, stderr) {
            console.log('*** stdout: ' + stdout);
            if (error !== null) {
                console.log('*** stderr: ' + error);
            }
        });
    });
    

    Python (Aufruf: scriptname.py <<Spielfeldlaenge>> <<Spielfeldbreite>> <<Torlänge>>):

    import sys
    import RPi.GPIO as GPIO          
    import time
    import datetime
    import math
    
    # Anzahl Argumente prüfen
    if len(sys.argv) != 4:
        print("*** Wrong number of script arguments.")
        print("*** call example: {sys.argv[0]} <<Spielfeldlaenge>> <<Spielfeldbreite>> <<Torlänge>>")
        quit(-1)
    
    def is_float(element: any) -> bool:
        #If you expect None to be passed:
        if element is None: 
            return False
        try:
            float(element)
            return True
        except ValueError:
            return False
    
    print("Total arguments passed:", len(sys.argv))
    
     
    in1 = 24
    in2 = 23   #Motor links
    en1 = 25
     
    in3 = 22
    in4 = 27#Motor rechts
    en2 = 17
    temp1=1
                #Reifen außen zu außen 45 cm
                #Reifen innen zu innen 35 cm
                #Linienbreite 10 cm
    GPIO.setmode(GPIO.BCM)
     
    GPIO.setup(in1,GPIO.OUT)
    GPIO.setup(in2,GPIO.OUT)
    GPIO.setup(en1,GPIO.OUT)
    GPIO.output(in1,GPIO.LOW)
    GPIO.output(in2,GPIO.LOW)
     
    GPIO.setup(in3,GPIO.OUT)
    GPIO.setup(in4,GPIO.OUT)
    GPIO.setup(en2,GPIO.OUT)
    GPIO.output(in3,GPIO.LOW)
    GPIO.output(in4,GPIO.LOW)
     
     
    p1=GPIO.PWM(en1,1000)
    p2=GPIO.PWM(en2,1000)
     
    p1.start(50) #Motor 1 Startgeschwindigkeit
    p2.start(50) #Motor 2 Startgeschwindigkeit
     
    l = sys.argv[1]
    if (not is_float(l)):
        print(f"error: argument {l} is not a float")
        quit(-1)
    l = float(l)
    print("Eingegeben wurde als Spielfeldlaenge: " + str(l))
    L = l/11
    print("Benötigte Zeit in s: " + str(L))   # Nur für mich Kontrolle
     
    b = sys.argv[2]
    if (not is_float(b)):
        print(f"error: argument {b} is not a float")
        quit(-1)
    b = float(b)
    print("Eingegeben wurde als Spielfeldbreite: " + str(l))
    B = b/11
    print("Benötigte Zeit in s: " + str(B))
     
    t = sys.argv[3]
    if (not is_float(t)):
        print(f"error: argument {t} is not a float")
        quit(-1)
    t = float(t)
    print("Eingegeben wurde als Torlänge: " + str(l))
    T = t/11
    print("Benötigte Zeit in s: " + str(T))
     
     
    Str1 = datetime.timedelta(seconds=L) # Fährt eingegeben Strecke
    start = datetime.datetime.now()
     
    while datetime.datetime.now()-start < Str1:
        
        if(temp1==1):  
           GPIO.output(in1,GPIO.HIGH)
           GPIO.output(in2,GPIO.LOW)           #Sprühen
           GPIO.output(in3,GPIO.HIGH)
           GPIO.output(in4,GPIO.LOW)
           print("Str1")
           time.sleep(1)
           
    GPIO.cleanup()
    
    

    Hoffe das hilft dir weiter.

    F Offline
    F Offline
    Fibs
    schrieb am zuletzt editiert von
    #12

    @rrov1 Kannst du mir erklären wie und was ich bei der vis einstellen muss

    rrov1R 1 Antwort Letzte Antwort
    0
    • F Fibs

      @rrov1 Kannst du mir erklären wie und was ich bei der vis einstellen muss

      rrov1R Offline
      rrov1R Offline
      rrov1
      schrieb am zuletzt editiert von
      #13

      @fibs said in Python3 Skript in Iobroker einbinden:

      @rrov1 Kannst du mir erklären wie und was ich bei der vis einstellen muss

      Ich wills versuchen. Vielleicht noch als Vorwort, ich persönlich nutze den Adapter vis für die Visualisierung. Warum, weil ich vor 3 Jahren damit angefangen habe und dabei geblieben bin, weil er für meinen Bedarf geeignet ist. Es gibt noch andere Adapter (älterer Vergleich) für die Erstellung von Visualisierungen, aber ich muss gestehen, ich kenne die nicht. Soweit ich beobachtet habe ist eine Folgeversion von vis in Entwicklung.

      Also ich würde das wie folgt aufsetzen:

      • 3 Datenpunkte zum abspeichern der Werte und zusätzlich habe ich mal noch einen Datnepunkt zum auslösen des Scriptes eingefügt (brauchen wir noch), einfach in ein neues Javascript einfügen und ausführen, damit die Datenpunkte angelegt sind:

        createState("GPIOSteuerung.Spielfeldlaenge", {
        read: true,
        write: true,
        name: "Spielfeldlaenge",
        type: "number",
        role: "value",
        desc: "Spielfeldlaenge",
        def: 0
        });
        createState("GPIOSteuerung.Spielfeldbreite", {
        read: true,
        write: true,
        name: "Spielfeldbreite",
        type: "number",
        role: "value",
        desc: "Spielfeldbreite",
        def: 0
        });
        createState("GPIOSteuerung.Torlänge", {
        read: true,
        write: true,
        name: "Torlänge",
        type: "number",
        role: "value",
        desc: "Torlänge",
        def: 0
        });
        createState("GPIOSteuerung.Ausfuehren", {
        read: true,
        write: true,
        name: "Ausfuehren",
        type: "boolean",
        role: "button",
        desc: "GPIO Steuerung ausführen",
        def: false
        });
      • Adapter "Visualisierung" installieren, Lizenz beschaffen (Community Lizenz siehe hier), danach den Editor aufrufen und ein neues Standardprojekt anlegen lassen.
      • Den Demo-View würde ich löschen und einen neuen, leeren anlegen (das farbliche Design überlasse ich Dir im weiteren, da ist vis sehr flexibel und bietet dementsprechend extrem viele Optionen)
      • Ab hier nutzen wir pro Datenpunkt 3 Objekte zu Darstellung:
        1. Ein "basic - HTML" Widget, wo wir einfach nur den Feldnamen reinschreiben damit man weiß, welchen der drei Werte man verändert
        2. Ein " basic - Number" Widget um den aktuellen Wert des Datenpunktes anzuzeigen. Das Widget ist mit dem korrespondierenden Datenpunkt verbunden.
        3. Ein "Slider horizontal" Widget um den Wert des Datenpunktes zu ändern. Das Widget ist mit dem korrespondierenden Datenpunkt verbunden.
      • Dann brauchen wir noch einen Button um das Script auszuführen, dafür taugt ein "Button state" Widget sehr gut.
      • Das GUI sieht dann so aus (nicht schön vom Design her, aber selten):
        645ce941-c426-4350-8032-38c0e561b047-image.png
      • Testen: Slider verschieben sollte sich im Objekt View auf den Datenpunkt auswirken
      • Ich habe dir mal den fertigen View exportiert, den kannst du im vis Editor auch einfach importieren (testview.txt )
      • Jetzt noch das Script für den Button zum ausführen (Achtung, neue Version, nicht das alte nehmen):
      on({id: "javascript.0.GPIOSteuerung.Ausfuehren", change: "any"}, function (obj) {
          var Spielfeldlaenge = getState("javascript.0.GPIOSteuerung.Spielfeldlaenge").val;
          var Spielfeldbreite = getState("javascript.0.GPIOSteuerung.Spielfeldbreite").val;
          var Torlaenge = getState("javascript.0.GPIOSteuerung.Torlaenge").val;
          console.log("führe aus: " + 'python3 /pfad/zum/script.py ' + Spielfeldlaenge + ' ' + Spielfeldbreite + ' ' + Torlaenge)
          exec('python3 /pfad/zum/script.py ' + Spielfeldlaenge + ' ' + Spielfeldbreite + ' ' + Torlaenge, function (error, stdout, stderr) {
              console.log('*** stdout: ' + stdout);
              if (error !== null) {
                  console.log('*** stderr: ' + error);
              }
          });
      });
      

      Damit sollte es gehen, das Python-Skript muss du natürlich noch hinlegen und den Pfad im Javascript anpassen.

      rrov1

      F 1 Antwort Letzte Antwort
      0
      • rrov1R rrov1

        @fibs said in Python3 Skript in Iobroker einbinden:

        @rrov1 Kannst du mir erklären wie und was ich bei der vis einstellen muss

        Ich wills versuchen. Vielleicht noch als Vorwort, ich persönlich nutze den Adapter vis für die Visualisierung. Warum, weil ich vor 3 Jahren damit angefangen habe und dabei geblieben bin, weil er für meinen Bedarf geeignet ist. Es gibt noch andere Adapter (älterer Vergleich) für die Erstellung von Visualisierungen, aber ich muss gestehen, ich kenne die nicht. Soweit ich beobachtet habe ist eine Folgeversion von vis in Entwicklung.

        Also ich würde das wie folgt aufsetzen:

        • 3 Datenpunkte zum abspeichern der Werte und zusätzlich habe ich mal noch einen Datnepunkt zum auslösen des Scriptes eingefügt (brauchen wir noch), einfach in ein neues Javascript einfügen und ausführen, damit die Datenpunkte angelegt sind:

          createState("GPIOSteuerung.Spielfeldlaenge", {
          read: true,
          write: true,
          name: "Spielfeldlaenge",
          type: "number",
          role: "value",
          desc: "Spielfeldlaenge",
          def: 0
          });
          createState("GPIOSteuerung.Spielfeldbreite", {
          read: true,
          write: true,
          name: "Spielfeldbreite",
          type: "number",
          role: "value",
          desc: "Spielfeldbreite",
          def: 0
          });
          createState("GPIOSteuerung.Torlänge", {
          read: true,
          write: true,
          name: "Torlänge",
          type: "number",
          role: "value",
          desc: "Torlänge",
          def: 0
          });
          createState("GPIOSteuerung.Ausfuehren", {
          read: true,
          write: true,
          name: "Ausfuehren",
          type: "boolean",
          role: "button",
          desc: "GPIO Steuerung ausführen",
          def: false
          });
        • Adapter "Visualisierung" installieren, Lizenz beschaffen (Community Lizenz siehe hier), danach den Editor aufrufen und ein neues Standardprojekt anlegen lassen.
        • Den Demo-View würde ich löschen und einen neuen, leeren anlegen (das farbliche Design überlasse ich Dir im weiteren, da ist vis sehr flexibel und bietet dementsprechend extrem viele Optionen)
        • Ab hier nutzen wir pro Datenpunkt 3 Objekte zu Darstellung:
          1. Ein "basic - HTML" Widget, wo wir einfach nur den Feldnamen reinschreiben damit man weiß, welchen der drei Werte man verändert
          2. Ein " basic - Number" Widget um den aktuellen Wert des Datenpunktes anzuzeigen. Das Widget ist mit dem korrespondierenden Datenpunkt verbunden.
          3. Ein "Slider horizontal" Widget um den Wert des Datenpunktes zu ändern. Das Widget ist mit dem korrespondierenden Datenpunkt verbunden.
        • Dann brauchen wir noch einen Button um das Script auszuführen, dafür taugt ein "Button state" Widget sehr gut.
        • Das GUI sieht dann so aus (nicht schön vom Design her, aber selten):
          645ce941-c426-4350-8032-38c0e561b047-image.png
        • Testen: Slider verschieben sollte sich im Objekt View auf den Datenpunkt auswirken
        • Ich habe dir mal den fertigen View exportiert, den kannst du im vis Editor auch einfach importieren (testview.txt )
        • Jetzt noch das Script für den Button zum ausführen (Achtung, neue Version, nicht das alte nehmen):
        on({id: "javascript.0.GPIOSteuerung.Ausfuehren", change: "any"}, function (obj) {
            var Spielfeldlaenge = getState("javascript.0.GPIOSteuerung.Spielfeldlaenge").val;
            var Spielfeldbreite = getState("javascript.0.GPIOSteuerung.Spielfeldbreite").val;
            var Torlaenge = getState("javascript.0.GPIOSteuerung.Torlaenge").val;
            console.log("führe aus: " + 'python3 /pfad/zum/script.py ' + Spielfeldlaenge + ' ' + Spielfeldbreite + ' ' + Torlaenge)
            exec('python3 /pfad/zum/script.py ' + Spielfeldlaenge + ' ' + Spielfeldbreite + ' ' + Torlaenge, function (error, stdout, stderr) {
                console.log('*** stdout: ' + stdout);
                if (error !== null) {
                    console.log('*** stderr: ' + error);
                }
            });
        });
        

        Damit sollte es gehen, das Python-Skript muss du natürlich noch hinlegen und den Pfad im Javascript anpassen.

        rrov1

        F Offline
        F Offline
        Fibs
        schrieb am zuletzt editiert von Fibs
        #14

        @rrov1 Irgendwo habe ich noch einen Fehler, habe alles so wie oben durchgeführt und bekomme auch keine Fehlermeldungen. Hier noch mein Log vllt findest du noch etwas aber irgendwas passt mit dem pfad nicht aber ich weiß nicht was.

        2c89ca95-e424-43c4-abe3-06067b8afc8c-image.png

        rrov1R 1 Antwort Letzte Antwort
        0
        • F Fibs

          @rrov1 Irgendwo habe ich noch einen Fehler, habe alles so wie oben durchgeführt und bekomme auch keine Fehlermeldungen. Hier noch mein Log vllt findest du noch etwas aber irgendwas passt mit dem pfad nicht aber ich weiß nicht was.

          2c89ca95-e424-43c4-abe3-06067b8afc8c-image.png

          rrov1R Offline
          rrov1R Offline
          rrov1
          schrieb am zuletzt editiert von
          #15

          @fibs Da fehlt ein Leerzeichen zwischen dem Scriptnamen und dem ersten Parameter. Schau mal in meinem Beispiel auf Zeile 6, nach dem ".py", da muss eins hin.

          F 1 Antwort Letzte Antwort
          0
          • rrov1R rrov1

            @fibs Da fehlt ein Leerzeichen zwischen dem Scriptnamen und dem ersten Parameter. Schau mal in meinem Beispiel auf Zeile 6, nach dem ".py", da muss eins hin.

            F Offline
            F Offline
            Fibs
            schrieb am zuletzt editiert von
            #16

            @rrov1
            Der Log Bereich sieht soweit gut aus. 9f0da957-87b6-4f0c-85b4-28dc14fe0fac-image.png
            aber es bewegt sich nichts. Wenn ich das Programm auf dem rpi direkt starte bekomme ich den Fehler "Process ended with exit code 255"

            rrov1R 1 Antwort Letzte Antwort
            0
            • F Fibs

              @rrov1
              Der Log Bereich sieht soweit gut aus. 9f0da957-87b6-4f0c-85b4-28dc14fe0fac-image.png
              aber es bewegt sich nichts. Wenn ich das Programm auf dem rpi direkt starte bekomme ich den Fehler "Process ended with exit code 255"

              rrov1R Offline
              rrov1R Offline
              rrov1
              schrieb am zuletzt editiert von
              #17

              @fibs Da wird's schwierig. Da ich grad keinen RPI zu Hand habe kann ich das auch nicht vollumfänglich testen, mein ioBroker läuft auf x86. Ich habe das Python-Skript von dir mal ausgeführt ohne RPI/GPIO spezifisches, das scheint sauber zu laufen. Neben der Fehlermeldung, in welcher Zeile tritt denn der Fehler auf? Ist es noch der gleiche Python Code wie weiter oben?

              F 1 Antwort Letzte Antwort
              0
              • rrov1R rrov1

                @fibs Da wird's schwierig. Da ich grad keinen RPI zu Hand habe kann ich das auch nicht vollumfänglich testen, mein ioBroker läuft auf x86. Ich habe das Python-Skript von dir mal ausgeführt ohne RPI/GPIO spezifisches, das scheint sauber zu laufen. Neben der Fehlermeldung, in welcher Zeile tritt denn der Fehler auf? Ist es noch der gleiche Python Code wie weiter oben?

                F Offline
                F Offline
                Fibs
                schrieb am zuletzt editiert von
                #18

                @rrov1 Es ist der gleiche Code den du mir oben genannt hast. Er arbeitet den Code bis Zeile 10 durch.

                rrov1R 1 Antwort Letzte Antwort
                0
                • F Fibs

                  @rrov1 Es ist der gleiche Code den du mir oben genannt hast. Er arbeitet den Code bis Zeile 10 durch.

                  rrov1R Offline
                  rrov1R Offline
                  rrov1
                  schrieb am zuletzt editiert von
                  #19

                  @fibs said in Python3 Skript in Iobroker einbinden:

                  @rrov1 Es ist der gleiche Code den du mir oben genannt hast. Er arbeitet den Code bis Zeile 10 durch.

                  Hm, also wenn's Zeile 10 ist, dann sehe ich einen kleinen Fehler in dieser. Ersetze sie mal mit:

                      print(f"*** call example: {sys.argv[0]} <<Spielfeldlaenge>> <<Spielfeldbreite>> <<Torlänge>>")
                  

                  Alternativ kommentiere sie aus. In den Zweig kommst du nur, wenn du die Parameter falsch angegeben hast, sprich zu wenig oder zu viele. Es müssen genau 3 Parameter sein, idealer Weise beim manuellen Testen erst mal nur ganze Zahlen. Dann wird dieser Teil des Codes auch nicht aktiv.

                  F 1 Antwort Letzte Antwort
                  0
                  • rrov1R rrov1

                    @fibs said in Python3 Skript in Iobroker einbinden:

                    @rrov1 Es ist der gleiche Code den du mir oben genannt hast. Er arbeitet den Code bis Zeile 10 durch.

                    Hm, also wenn's Zeile 10 ist, dann sehe ich einen kleinen Fehler in dieser. Ersetze sie mal mit:

                        print(f"*** call example: {sys.argv[0]} <<Spielfeldlaenge>> <<Spielfeldbreite>> <<Torlänge>>")
                    

                    Alternativ kommentiere sie aus. In den Zweig kommst du nur, wenn du die Parameter falsch angegeben hast, sprich zu wenig oder zu viele. Es müssen genau 3 Parameter sein, idealer Weise beim manuellen Testen erst mal nur ganze Zahlen. Dann wird dieser Teil des Codes auch nicht aktiv.

                    F Offline
                    F Offline
                    Fibs
                    schrieb am zuletzt editiert von
                    #20

                    @rrov1 Hä warte mal, kann das so überhaupt funktionieren mit den Datenpunkten Spielfeldlaenge, Spielfeldbreite und Torlaenge. Die Variablen in meinem Projekt heißen ja, l,b, und t . Die Namen kommen nur einmal vor und zwar bei der Aufforderung was einzugeben ist.

                    rrov1R 1 Antwort Letzte Antwort
                    0
                    • F Fibs

                      @rrov1 Hä warte mal, kann das so überhaupt funktionieren mit den Datenpunkten Spielfeldlaenge, Spielfeldbreite und Torlaenge. Die Variablen in meinem Projekt heißen ja, l,b, und t . Die Namen kommen nur einmal vor und zwar bei der Aufforderung was einzugeben ist.

                      rrov1R Offline
                      rrov1R Offline
                      rrov1
                      schrieb am zuletzt editiert von
                      #21

                      @fibs Nun, die Zeile 10 wird nur dann aufgerufen, wenn die Anzahl der Parameter falsch ist. Es ist die Ausgabe vom Script die dem aufrufenden Nutzer sagt wie der das Script nutzen soll (vergleichbar mit dem Schalter -h für "Hilfe"). In der Zeile findet keine Zuweisung zu einer Variablen statt. Das passiert in den Zeilen 58, 67 und 76. Alles im grünen Bereich :-)

                      F 1 Antwort Letzte Antwort
                      0
                      • rrov1R rrov1

                        @fibs Nun, die Zeile 10 wird nur dann aufgerufen, wenn die Anzahl der Parameter falsch ist. Es ist die Ausgabe vom Script die dem aufrufenden Nutzer sagt wie der das Script nutzen soll (vergleichbar mit dem Schalter -h für "Hilfe"). In der Zeile findet keine Zuweisung zu einer Variablen statt. Das passiert in den Zeilen 58, 67 und 76. Alles im grünen Bereich :-)

                        F Offline
                        F Offline
                        Fibs
                        schrieb am zuletzt editiert von
                        #22

                        @rrov1 Aber grundsätzlich sollen die Motoren starten wenn ich den Button in der visu drücke oder muss ich noch irgendwas beachten?

                        rrov1R 1 Antwort Letzte Antwort
                        0
                        • F Fibs

                          @rrov1 Aber grundsätzlich sollen die Motoren starten wenn ich den Button in der visu drücke oder muss ich noch irgendwas beachten?

                          rrov1R Offline
                          rrov1R Offline
                          rrov1
                          schrieb am zuletzt editiert von
                          #23

                          @fibs ganz genau, erst die 3 Regler einstellen, dann den Button drücken (kannst du später immer noch optimieren). Ich denk auf ioBroker Seite sieht's soweit ganz gut aus wenn ich den letzten Screenshot wo noch der Pfad falsch war lese.

                          Läuft das Script jetzt mit der Korrektur der Zeile 10 wenn du es von der Kommandozeile mit 3 sinnvollen Parametern aufrufst?

                          F 1 Antwort Letzte Antwort
                          0
                          • rrov1R rrov1

                            @fibs ganz genau, erst die 3 Regler einstellen, dann den Button drücken (kannst du später immer noch optimieren). Ich denk auf ioBroker Seite sieht's soweit ganz gut aus wenn ich den letzten Screenshot wo noch der Pfad falsch war lese.

                            Läuft das Script jetzt mit der Korrektur der Zeile 10 wenn du es von der Kommandozeile mit 3 sinnvollen Parametern aufrufst?

                            F Offline
                            F Offline
                            Fibs
                            schrieb am zuletzt editiert von Fibs
                            #24

                            @rrov1
                            Ich habe Zeile 10 ausgeklammert und das Programm manuell gestartet. Anders funktionierts noch nicht.

                            F 1 Antwort Letzte Antwort
                            0
                            • F Fibs

                              @rrov1
                              Ich habe Zeile 10 ausgeklammert und das Programm manuell gestartet. Anders funktionierts noch nicht.

                              F Offline
                              F Offline
                              Fibs
                              schrieb am zuletzt editiert von
                              #25

                              @fibs a5951760-0555-4c92-af62-46467ab3b6b3-image.png
                              Ich habe den Button über Objekte betätigt, das ist e egal oder?

                              rrov1R 1 Antwort Letzte Antwort
                              0
                              • F Fibs

                                @fibs a5951760-0555-4c92-af62-46467ab3b6b3-image.png
                                Ich habe den Button über Objekte betätigt, das ist e egal oder?

                                rrov1R Offline
                                rrov1R Offline
                                rrov1
                                schrieb am zuletzt editiert von
                                #26

                                @fibs said in Python3 Skript in Iobroker einbinden:

                                Ich habe den Button über Objekte betätigt, das ist e egal oder?

                                Ja, ist egal. Das Log ist leider für mich nicht ausreichend um den Fehler zu ermitteln. Kannst du bitte noch mal das Javascript "DC-Motoren_starten" hier bereitstellen? Ich vermute mal es ist mein Script, aber vielleicht müssen wir mal etwas Code einfügen der noch ein bisschen mehr protokolliert. Es fehlt die Ausgabe des exec Aufrufst, das sollte mit "*** stdout:" anfangen und falls ein Fehler auftritt "*** stderr:".

                                Zusätzlich müssen wir wahrscheinlich das Python-Skript auch mal anfassen um zu sehen ob es läuft. Momentan sehen wir ja garnichts, nicht mal das es läuft. Ich ersetze das dann meist erst mal mit was ganz trivialen, was z.B.:

                                print("hello world")
                                

                                Dann wüsste man erst mal ob der Aufruf aus der VIS heraus sauber funktioniert (weil man das ja als stdout zurückbekommt). Dann tastet man sich weiter vor, indem man 90% vom eigentlichen Script auskommentiert, das ausführt und wenn's geht wieder 10% Kommentare entfernt, bis man mal grob eingegrenzt hat wo im Code es hängt.

                                F 1 Antwort Letzte Antwort
                                0
                                • rrov1R rrov1

                                  @fibs said in Python3 Skript in Iobroker einbinden:

                                  Ich habe den Button über Objekte betätigt, das ist e egal oder?

                                  Ja, ist egal. Das Log ist leider für mich nicht ausreichend um den Fehler zu ermitteln. Kannst du bitte noch mal das Javascript "DC-Motoren_starten" hier bereitstellen? Ich vermute mal es ist mein Script, aber vielleicht müssen wir mal etwas Code einfügen der noch ein bisschen mehr protokolliert. Es fehlt die Ausgabe des exec Aufrufst, das sollte mit "*** stdout:" anfangen und falls ein Fehler auftritt "*** stderr:".

                                  Zusätzlich müssen wir wahrscheinlich das Python-Skript auch mal anfassen um zu sehen ob es läuft. Momentan sehen wir ja garnichts, nicht mal das es läuft. Ich ersetze das dann meist erst mal mit was ganz trivialen, was z.B.:

                                  print("hello world")
                                  

                                  Dann wüsste man erst mal ob der Aufruf aus der VIS heraus sauber funktioniert (weil man das ja als stdout zurückbekommt). Dann tastet man sich weiter vor, indem man 90% vom eigentlichen Script auskommentiert, das ausführt und wenn's geht wieder 10% Kommentare entfernt, bis man mal grob eingegrenzt hat wo im Code es hängt.

                                  F Offline
                                  F Offline
                                  Fibs
                                  schrieb am zuletzt editiert von
                                  #27

                                  @rrov1 ```
                                  import sys
                                  import RPi.GPIO as GPIO
                                  import time
                                  import datetime
                                  import math

                                  Anzahl Argumente prüfen

                                  if len(sys.argv) != 4:
                                  print("*** Wrong number of script arguments.")
                                  print("f*** call example: {sys.argv[0]} <<Spielfeldlaenge>> <<Spielfeldbreite>> <<Torlaenge>>")
                                  quit(-1)

                                  def is_float(element: any) -> bool:
                                  #If you expect None to be passed:
                                  if element is None:
                                  return False
                                  try:
                                  float(element)
                                  return True
                                  except ValueError:
                                  return False

                                  print("Total arguments passed:", len(sys.argv))

                                  in1 = 24
                                  in2 = 23 #Motor links
                                  en1 = 25

                                  in3 = 22
                                  in4 = 27#Motor rechts
                                  en2 = 17
                                  temp1=1
                                  #Reifen außen zu außen 45 cm
                                  #Reifen innen zu innen 35 cm
                                  #Linienbreite 10 cm
                                  GPIO.setmode(GPIO.BCM)

                                  GPIO.setup(in1,GPIO.OUT)
                                  GPIO.setup(in2,GPIO.OUT)
                                  GPIO.setup(en1,GPIO.OUT)
                                  GPIO.output(in1,GPIO.LOW)
                                  GPIO.output(in2,GPIO.LOW)

                                  GPIO.setup(in3,GPIO.OUT)
                                  GPIO.setup(in4,GPIO.OUT)
                                  GPIO.setup(en2,GPIO.OUT)
                                  GPIO.output(in3,GPIO.LOW)
                                  GPIO.output(in4,GPIO.LOW)

                                  p1=GPIO.PWM(en1,1000)
                                  p2=GPIO.PWM(en2,1000)

                                  p1.start(50) #Motor 1 Startgeschwindigkeit
                                  p2.start(50) #Motor 2 Startgeschwindigkeit

                                  l = input("Bitte geben Sie die Spielfeldlaenge in cm ein: ")
                                  l = float(l)
                                  print("Eingegeben wurde: " + str(l))
                                  L = l/11
                                  print("Benötigte Zeit in s: " + str(L)) # Nur für mich Kontrolle

                                  b = input("Bitte geben Sie die Spielfeldbreite in cm ein: ")
                                  b = float(b)
                                  print("Eingegeben wurde: " + str(l))
                                  B = b/11
                                  print("Benötigte Zeit in s: " + str(B))

                                  t = input("Bitte geben Sie die Torlaenge in cm ein: ")
                                  t = float(t)
                                  print("Eingegeben wurde: " + str(l))
                                  T = t/11

                                  s = input("Bitte geben Sie die Entfernung von Torstange zu 16ner Ecke in cm ein: ")
                                  s = float(s)
                                  print("Eingegeben wurde: " + str(s))
                                  S = s/11
                                  print("Benötigte Zeit in s: " + str(S))

                                  Str1 = datetime.timedelta(seconds=L) # Fährt eingegeben Strecke
                                  start = datetime.datetime.now()

                                  while datetime.datetime.now()-start < Str1:

                                  if(temp1==1):  
                                     GPIO.output(in1,GPIO.HIGH)
                                     GPIO.output(in2,GPIO.LOW)           #Sprühen
                                     GPIO.output(in3,GPIO.HIGH)
                                     GPIO.output(in4,GPIO.LOW)
                                     print("Str1")
                                     time.sleep(1)
                                  

                                  GPIO.cleanup()

                                  F 1 Antwort Letzte Antwort
                                  0
                                  • F Fibs

                                    @rrov1 ```
                                    import sys
                                    import RPi.GPIO as GPIO
                                    import time
                                    import datetime
                                    import math

                                    Anzahl Argumente prüfen

                                    if len(sys.argv) != 4:
                                    print("*** Wrong number of script arguments.")
                                    print("f*** call example: {sys.argv[0]} <<Spielfeldlaenge>> <<Spielfeldbreite>> <<Torlaenge>>")
                                    quit(-1)

                                    def is_float(element: any) -> bool:
                                    #If you expect None to be passed:
                                    if element is None:
                                    return False
                                    try:
                                    float(element)
                                    return True
                                    except ValueError:
                                    return False

                                    print("Total arguments passed:", len(sys.argv))

                                    in1 = 24
                                    in2 = 23 #Motor links
                                    en1 = 25

                                    in3 = 22
                                    in4 = 27#Motor rechts
                                    en2 = 17
                                    temp1=1
                                    #Reifen außen zu außen 45 cm
                                    #Reifen innen zu innen 35 cm
                                    #Linienbreite 10 cm
                                    GPIO.setmode(GPIO.BCM)

                                    GPIO.setup(in1,GPIO.OUT)
                                    GPIO.setup(in2,GPIO.OUT)
                                    GPIO.setup(en1,GPIO.OUT)
                                    GPIO.output(in1,GPIO.LOW)
                                    GPIO.output(in2,GPIO.LOW)

                                    GPIO.setup(in3,GPIO.OUT)
                                    GPIO.setup(in4,GPIO.OUT)
                                    GPIO.setup(en2,GPIO.OUT)
                                    GPIO.output(in3,GPIO.LOW)
                                    GPIO.output(in4,GPIO.LOW)

                                    p1=GPIO.PWM(en1,1000)
                                    p2=GPIO.PWM(en2,1000)

                                    p1.start(50) #Motor 1 Startgeschwindigkeit
                                    p2.start(50) #Motor 2 Startgeschwindigkeit

                                    l = input("Bitte geben Sie die Spielfeldlaenge in cm ein: ")
                                    l = float(l)
                                    print("Eingegeben wurde: " + str(l))
                                    L = l/11
                                    print("Benötigte Zeit in s: " + str(L)) # Nur für mich Kontrolle

                                    b = input("Bitte geben Sie die Spielfeldbreite in cm ein: ")
                                    b = float(b)
                                    print("Eingegeben wurde: " + str(l))
                                    B = b/11
                                    print("Benötigte Zeit in s: " + str(B))

                                    t = input("Bitte geben Sie die Torlaenge in cm ein: ")
                                    t = float(t)
                                    print("Eingegeben wurde: " + str(l))
                                    T = t/11

                                    s = input("Bitte geben Sie die Entfernung von Torstange zu 16ner Ecke in cm ein: ")
                                    s = float(s)
                                    print("Eingegeben wurde: " + str(s))
                                    S = s/11
                                    print("Benötigte Zeit in s: " + str(S))

                                    Str1 = datetime.timedelta(seconds=L) # Fährt eingegeben Strecke
                                    start = datetime.datetime.now()

                                    while datetime.datetime.now()-start < Str1:

                                    if(temp1==1):  
                                       GPIO.output(in1,GPIO.HIGH)
                                       GPIO.output(in2,GPIO.LOW)           #Sprühen
                                       GPIO.output(in3,GPIO.HIGH)
                                       GPIO.output(in4,GPIO.LOW)
                                       print("Str1")
                                       time.sleep(1)
                                    

                                    GPIO.cleanup()

                                    F Offline
                                    F Offline
                                    Fibs
                                    schrieb am zuletzt editiert von Fibs
                                    #28

                                    @fibs said in Python3 Skript in Iobroker einbinden:

                                    import sys
                                    import RPi.GPIO as GPIO
                                    import time
                                    import datetime
                                    import math
                                    Anzahl Argumente prüfen
                                    if len(sys.argv) != 4:
                                    print("*** Wrong number of script arguments.")
                                    print("f*** call example: {sys.argv[0]} <<Spielfeldlaenge>> <<Spielfeldbreite>> <<Torlaenge>>")
                                    quit(-1)
                                    def is_float(element: any) -> bool:
                                    #If you expect None to be passed:
                                    if element is None:
                                    return False
                                    try:
                                    float(element)
                                    return True
                                    except ValueError:
                                    return False
                                    print("Total arguments passed:", len(sys.argv))
                                    in1 = 24
                                    in2 = 23 #Motor links
                                    en1 = 25
                                    in3 = 22
                                    in4 = 27#Motor rechts
                                    en2 = 17
                                    temp1=1
                                    #Reifen außen zu außen 45 cm
                                    #Reifen innen zu innen 35 cm
                                    #Linienbreite 10 cm
                                    GPIO.setmode(GPIO.BCM)
                                    GPIO.setup(in1,GPIO.OUT)
                                    GPIO.setup(in2,GPIO.OUT)
                                    GPIO.setup(en1,GPIO.OUT)
                                    GPIO.output(in1,GPIO.LOW)
                                    GPIO.output(in2,GPIO.LOW)
                                    GPIO.setup(in3,GPIO.OUT)
                                    GPIO.setup(in4,GPIO.OUT)
                                    GPIO.setup(en2,GPIO.OUT)
                                    GPIO.output(in3,GPIO.LOW)
                                    GPIO.output(in4,GPIO.LOW)
                                    p1=GPIO.PWM(en1,1000)
                                    p2=GPIO.PWM(en2,1000)
                                    p1.start(50) #Motor 1 Startgeschwindigkeit
                                    p2.start(50) #Motor 2 Startgeschwindigkeit
                                    l = input("Bitte geben Sie die Spielfeldlaenge in cm ein: ")
                                    l = float(l)
                                    print("Eingegeben wurde: " + str(l))
                                    L = l/11
                                    print("Benötigte Zeit in s: " + str(L)) # Nur für mich Kontrolle
                                    b = input("Bitte geben Sie die Spielfeldbreite in cm ein: ")
                                    b = float(b)
                                    print("Eingegeben wurde: " + str(l))
                                    B = b/11
                                    print("Benötigte Zeit in s: " + str(B))
                                    t = input("Bitte geben Sie die Torlaenge in cm ein: ")
                                    t = float(t)
                                    print("Eingegeben wurde: " + str(l))
                                    T = t/11
                                    s = input("Bitte geben Sie die Entfernung von Torstange zu 16ner Ecke in cm ein: ")
                                    s = float(s)
                                    print("Eingegeben wurde: " + str(s))
                                    S = s/11
                                    print("Benötigte Zeit in s: " + str(S))
                                    Str1 = datetime.timedelta(seconds=L) # Fährt eingegeben Strecke
                                    start = datetime.datetime.now()
                                    while datetime.datetime.now()-start < Str1:
                                    if(temp1==1): GPIO.output(in1,GPIO.HIGH)
                                    GPIO.output(in2,GPIO.LOW)
                                    GPIO.output(in3,GPIO.HIGH)
                                    GPIO.output(in4,GPIO.LOW)
                                    print("Str1") time.sleep(1)
                                    GPIO.cleanup()

                                    F rrov1R 2 Antworten Letzte Antwort
                                    0
                                    • F Fibs

                                      @fibs said in Python3 Skript in Iobroker einbinden:

                                      import sys
                                      import RPi.GPIO as GPIO
                                      import time
                                      import datetime
                                      import math
                                      Anzahl Argumente prüfen
                                      if len(sys.argv) != 4:
                                      print("*** Wrong number of script arguments.")
                                      print("f*** call example: {sys.argv[0]} <<Spielfeldlaenge>> <<Spielfeldbreite>> <<Torlaenge>>")
                                      quit(-1)
                                      def is_float(element: any) -> bool:
                                      #If you expect None to be passed:
                                      if element is None:
                                      return False
                                      try:
                                      float(element)
                                      return True
                                      except ValueError:
                                      return False
                                      print("Total arguments passed:", len(sys.argv))
                                      in1 = 24
                                      in2 = 23 #Motor links
                                      en1 = 25
                                      in3 = 22
                                      in4 = 27#Motor rechts
                                      en2 = 17
                                      temp1=1
                                      #Reifen außen zu außen 45 cm
                                      #Reifen innen zu innen 35 cm
                                      #Linienbreite 10 cm
                                      GPIO.setmode(GPIO.BCM)
                                      GPIO.setup(in1,GPIO.OUT)
                                      GPIO.setup(in2,GPIO.OUT)
                                      GPIO.setup(en1,GPIO.OUT)
                                      GPIO.output(in1,GPIO.LOW)
                                      GPIO.output(in2,GPIO.LOW)
                                      GPIO.setup(in3,GPIO.OUT)
                                      GPIO.setup(in4,GPIO.OUT)
                                      GPIO.setup(en2,GPIO.OUT)
                                      GPIO.output(in3,GPIO.LOW)
                                      GPIO.output(in4,GPIO.LOW)
                                      p1=GPIO.PWM(en1,1000)
                                      p2=GPIO.PWM(en2,1000)
                                      p1.start(50) #Motor 1 Startgeschwindigkeit
                                      p2.start(50) #Motor 2 Startgeschwindigkeit
                                      l = input("Bitte geben Sie die Spielfeldlaenge in cm ein: ")
                                      l = float(l)
                                      print("Eingegeben wurde: " + str(l))
                                      L = l/11
                                      print("Benötigte Zeit in s: " + str(L)) # Nur für mich Kontrolle
                                      b = input("Bitte geben Sie die Spielfeldbreite in cm ein: ")
                                      b = float(b)
                                      print("Eingegeben wurde: " + str(l))
                                      B = b/11
                                      print("Benötigte Zeit in s: " + str(B))
                                      t = input("Bitte geben Sie die Torlaenge in cm ein: ")
                                      t = float(t)
                                      print("Eingegeben wurde: " + str(l))
                                      T = t/11
                                      s = input("Bitte geben Sie die Entfernung von Torstange zu 16ner Ecke in cm ein: ")
                                      s = float(s)
                                      print("Eingegeben wurde: " + str(s))
                                      S = s/11
                                      print("Benötigte Zeit in s: " + str(S))
                                      Str1 = datetime.timedelta(seconds=L) # Fährt eingegeben Strecke
                                      start = datetime.datetime.now()
                                      while datetime.datetime.now()-start < Str1:
                                      if(temp1==1): GPIO.output(in1,GPIO.HIGH)
                                      GPIO.output(in2,GPIO.LOW)
                                      GPIO.output(in3,GPIO.HIGH)
                                      GPIO.output(in4,GPIO.LOW)
                                      print("Str1") time.sleep(1)
                                      GPIO.cleanup()

                                      F Offline
                                      F Offline
                                      Fibs
                                      schrieb am zuletzt editiert von Fibs
                                      #29

                                      @fibs

                                      on({id: "javascript.0.GPIOSteuerung.Ausfuehren", change: "any"}, function (obj) {
                                      var Spielfeldlaenge = getState("javascript.0.GPIOSteuerung.Spielfeldlaenge").val;
                                      var Spielfeldbreite = getState("javascript.0.GPIOSteuerung.Spielfeldbreite").val;
                                      var Torlaenge = getState("javascript.0.GPIOSteuerung.Torlaenge").val;
                                      console.log("führe aus: " + 'python3 /Desktop/iobroker/DA/Main.py ' + Spielfeldlaenge + ' ' + Spielfeldbreite + ' ' + Torlaenge)
                                      exec('python3 /Desktop/iobroker/DA/Main.py ' + Spielfeldlaenge + ' ' + Spielfeldbreite + ' ' + Torlaenge, function (error, stdout, stderr) {
                                      console.log('*** stdout: ' + stdout);
                                      if (error !== null) {
                                      console.log('*** stderr: ' + error);
                                      }
                                      });
                                      });

                                      1 Antwort Letzte Antwort
                                      0
                                      • F Fibs

                                        @fibs said in Python3 Skript in Iobroker einbinden:

                                        import sys
                                        import RPi.GPIO as GPIO
                                        import time
                                        import datetime
                                        import math
                                        Anzahl Argumente prüfen
                                        if len(sys.argv) != 4:
                                        print("*** Wrong number of script arguments.")
                                        print("f*** call example: {sys.argv[0]} <<Spielfeldlaenge>> <<Spielfeldbreite>> <<Torlaenge>>")
                                        quit(-1)
                                        def is_float(element: any) -> bool:
                                        #If you expect None to be passed:
                                        if element is None:
                                        return False
                                        try:
                                        float(element)
                                        return True
                                        except ValueError:
                                        return False
                                        print("Total arguments passed:", len(sys.argv))
                                        in1 = 24
                                        in2 = 23 #Motor links
                                        en1 = 25
                                        in3 = 22
                                        in4 = 27#Motor rechts
                                        en2 = 17
                                        temp1=1
                                        #Reifen außen zu außen 45 cm
                                        #Reifen innen zu innen 35 cm
                                        #Linienbreite 10 cm
                                        GPIO.setmode(GPIO.BCM)
                                        GPIO.setup(in1,GPIO.OUT)
                                        GPIO.setup(in2,GPIO.OUT)
                                        GPIO.setup(en1,GPIO.OUT)
                                        GPIO.output(in1,GPIO.LOW)
                                        GPIO.output(in2,GPIO.LOW)
                                        GPIO.setup(in3,GPIO.OUT)
                                        GPIO.setup(in4,GPIO.OUT)
                                        GPIO.setup(en2,GPIO.OUT)
                                        GPIO.output(in3,GPIO.LOW)
                                        GPIO.output(in4,GPIO.LOW)
                                        p1=GPIO.PWM(en1,1000)
                                        p2=GPIO.PWM(en2,1000)
                                        p1.start(50) #Motor 1 Startgeschwindigkeit
                                        p2.start(50) #Motor 2 Startgeschwindigkeit
                                        l = input("Bitte geben Sie die Spielfeldlaenge in cm ein: ")
                                        l = float(l)
                                        print("Eingegeben wurde: " + str(l))
                                        L = l/11
                                        print("Benötigte Zeit in s: " + str(L)) # Nur für mich Kontrolle
                                        b = input("Bitte geben Sie die Spielfeldbreite in cm ein: ")
                                        b = float(b)
                                        print("Eingegeben wurde: " + str(l))
                                        B = b/11
                                        print("Benötigte Zeit in s: " + str(B))
                                        t = input("Bitte geben Sie die Torlaenge in cm ein: ")
                                        t = float(t)
                                        print("Eingegeben wurde: " + str(l))
                                        T = t/11
                                        s = input("Bitte geben Sie die Entfernung von Torstange zu 16ner Ecke in cm ein: ")
                                        s = float(s)
                                        print("Eingegeben wurde: " + str(s))
                                        S = s/11
                                        print("Benötigte Zeit in s: " + str(S))
                                        Str1 = datetime.timedelta(seconds=L) # Fährt eingegeben Strecke
                                        start = datetime.datetime.now()
                                        while datetime.datetime.now()-start < Str1:
                                        if(temp1==1): GPIO.output(in1,GPIO.HIGH)
                                        GPIO.output(in2,GPIO.LOW)
                                        GPIO.output(in3,GPIO.HIGH)
                                        GPIO.output(in4,GPIO.LOW)
                                        print("Str1") time.sleep(1)
                                        GPIO.cleanup()

                                        rrov1R Offline
                                        rrov1R Offline
                                        rrov1
                                        schrieb am zuletzt editiert von
                                        #30

                                        @fibs Das Python-Skript passt nicht. Zum einen fehlen an verschiedenen Stellen die Einrückungen, wobei ich vermute mal das liegt ein der Einbettung des Codes hier im Forum, zum anderen sind wieder die input()-Funktionsaufrufe drinnen, welche dazu führen, dass das Skript stehen bleibt und auf Eingabe wartet. Ich habe dir noch mal eine Version mit Parametern hier beigelegt: Main.py .
                                        Was mir noch aufgefallen ist, du hast jetzt einen vierten Wert den du per input() Abfragst, den habe ich gleich mit als jetzt 4 Parameter eingebaut. Damit brauchst du jetzt auch einen vierten Datenpunkt in ioBroker + einen vierten Parameter im Javascript. Nicht vergessen, sonst geht das nicht.

                                        1 Antwort Letzte Antwort
                                        0
                                        Antworten
                                        • In einem neuen Thema antworten
                                        Anmelden zum Antworten
                                        • Älteste zuerst
                                        • Neuste zuerst
                                        • Meiste Stimmen


                                        Support us

                                        ioBroker
                                        Community Adapters
                                        Donate

                                        315

                                        Online

                                        32.6k

                                        Benutzer

                                        82.3k

                                        Themen

                                        1.3m

                                        Beiträge
                                        Community
                                        Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                        ioBroker Community 2014-2025
                                        logo
                                        • Anmelden

                                        • Du hast noch kein Konto? Registrieren

                                        • Anmelden oder registrieren, um zu suchen
                                        • Erster Beitrag
                                          Letzter Beitrag
                                        0
                                        • Home
                                        • Aktuell
                                        • Tags
                                        • Ungelesen 0
                                        • Kategorien
                                        • Unreplied
                                        • Beliebt
                                        • GitHub
                                        • Docu
                                        • Hilfe