Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. [Gelöst]Python prozess wird nach Zeit X mehrfach ausgeführt.

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    [Gelöst]Python prozess wird nach Zeit X mehrfach ausgeführt.

    This topic has been deleted. Only users with topic management privileges can see it.
    • wendy2702
      wendy2702 last edited by wendy2702

      Hi,

      um meinen Felicity Akku auslesen zu können läuft auf einem Pi3B mit Bookworm ein Python script welches ich in einem anderen Forum gefunden und angepasst habe.

      Das Script und die Abfrage funktioniert soweit und läuft als Service auf dem PI.

      mirko@felicity:~ $ systemctl status FelicityBMS.service
      ● FelicityBMS.service - hit service
           Loaded: loaded (/etc/systemd/system/FelicityBMS.service; enabled; preset: enabled)
           Active: active (running) since Wed 2025-02-26 17:27:24 CET; 4min 0s ago
         Main PID: 580 (python)
            Tasks: 2 (limit: 767)
              CPU: 1.824s
           CGroup: /system.slice/FelicityBMS.service
                   └─580 /usr/bin/python /home/mirko/felicityBMSscript/BMSsnippet_iob_leon.py
      
      Feb 26 17:27:24 felicity systemd[1]: Started FelicityBMS.service - hit service.
      
      

      Der Service scheint dauerhaft stabil zu laufen, seit letztem restart des PI's

      mirko@felicity:~ $ sudo journalctl -f -u FelicityBMS.service
      Feb 26 17:27:24 felicity systemd[1]: Started FelicityBMS.service - hit service.
      
      

      Das Script sieht so aus:

      mirko@felicity:~/felicityBMSscript $ cat BMSsnippet_iob_leon.py
      import logging
      import signal
      import sys
      import paho.mqtt.client as mqtt
      import datetime
      import time
      import os.path
      from FelicityBMSManager import FelicityBMSManager
      
      # Configure logging
      logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
      
      #DataItem = namedtuple("DataItem", ["key", "command", "data", "lastdata", "isdirty"])
      class DataItem:
      
         def __init__(self, command : str, clientid : int):
             self.command = command
             self.clientid = clientid
             self.data = None
             self.lastdata = None
      
      class MQTTBroker:
      
         def __init__(self, name: str, address : str, topic : str):
             self.name = name
             self.address = address
             self.topic = topic
             self.client = None
      
      
      ioBroker_broker = MQTTBroker('ioBroker', '192.168.178.18', 'felicity/battery')
      
      def on_connect(client, userdata, rc, *extra_params):
         print('ioBroker: Connected with result code ' + str(rc))
         client.subscribe(ioBroker_broker.topic + '/set/#')
         #client.publish(settings.MQTT_TOPIC + '', get_gpio_status(), 1)
      
      
      ioBroker_broker.client = mqtt.Client()
      isrunning = True
      
      def _handle_sigterm(sig, frame):
         logging.info("SIGTERM received. Exiting...")
         isrunning = False
         ioBroker_broker.client.loop_stop()
         exit()
      
      def getFormattedData(command, clientid):
         ws = FelicityBMSManager(command=command, clientid=clientid)
         data = ws.get_data()
      
         #if websocket_data != last_websocket_data:
      
         formatted_data = {}
      
         for inverter_key in data:
             inverter_item = data[inverter_key]
             value = inverter_item.value
      
             #if value == '--':
             #    value = '0'
      
             formatted_data[inverter_key] = {"name": inverter_item.name, "value": value, "unit": inverter_item.unit}
             #print(inverter_key, inverter_item.desc, value, inverter_item.unit)
      
         return formatted_data
      
      def sendData(broker, topic_key, data):
         broker.client.publish(broker.topic + topic_key, data)
         #print(broker.name, broker.address, broker.topic + topic_key, data)
      
      starttime = datetime.datetime.min
      resettime = datetime.datetime.min
      
      try:
         signal.signal(signal.SIGTERM, _handle_sigterm)
      
         ioBroker_broker.client.on_connect = on_connect
         #ioBroker_broker.client.on_message = on_message
         ioBroker_broker.client.username_pw_set("mqtt","ioBroker")
         ioBroker_broker.client.connect(ioBroker_broker.address, 1889, 60)
         ioBroker_broker.client.loop_start()
      
         starttime = datetime.datetime.min
      
         battery_information_list = [
             DataItem(command="GetBMSBatteryInformation", clientid = 1),
             DataItem(command="GetBMSBatteryInformation", clientid = 2),
             DataItem(command="GetBMSBatteryInformation", clientid = 3),
             DataItem(command="GetBMSBatteryInformation", clientid = 4)
         ]
      
         cell_information_list = [DataItem(command="GetBMSCellInformation", clientid = battery_information.clientid) for battery_information in battery_information_list]
      
         while isrunning:
             if datetime.datetime.now() > starttime + datetime.timedelta(seconds = 10): #org 10
                 try:
                     isDirtyDefault = False
      
                     if datetime.datetime.now() > resettime + datetime.timedelta(seconds = 60): #org 60
                         isDirtyDefault = True
                         resettime = datetime.datetime.now()
      
                     for battery_index, battery_information in enumerate(battery_information_list):
                         battery_information.lastdata = battery_information.data
      
                         battery_information.data = getFormattedData(command =  battery_information.command, clientid = battery_information.clientid)
                         time.sleep(1)
      
                         if isDirtyDefault or battery_information.lastdata != battery_information.data:
                             battery_voltage = battery_information.data["BatteryVoltage"]["value"]
                             battery_current = battery_information.data["BatteryCurrent"]["value"]
                             battery_power = battery_voltage * battery_current * -1 # positiv Ladung, negativ Entladung
                             battery_soc = battery_information.data["SOC"]["value"]
      
                             sendData(ioBroker_broker, '/' + str(battery_information.clientid) + '/battery_voltage', battery_voltage)
                             sendData(ioBroker_broker, '/' + str(battery_information.clientid) + '/battery_current', battery_current)
                             sendData(ioBroker_broker, '/' + str(battery_information.clientid) + '/battery_power', round(battery_power, 1))
                             sendData(ioBroker_broker, '/' + str(battery_information.clientid) + '/soc', battery_soc)
      
                         cell_information = cell_information_list[battery_index]
                         cell_information.lastdata = cell_information.data
                         cell_information.data = getFormattedData(command = cell_information.command, clientid = cell_information.clientid)
                         time.sleep(1)
      
                         if isDirtyDefault or cell_information.lastdata != cell_information.data:
                             for cell_index in range(1, 17):
                                 cell_voltage = cell_information.data["Cell" + str(cell_index) + " Voltage"]["value"]
                                 sendData(ioBroker_broker, '/' + str(battery_information.clientid) + '/cell_' + str(cell_index) + '_voltage', cell_voltage)
      
                 except Exception as e:
                     exc_type, exc_obj, exc_tb = sys.exc_info()
                     fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
                     logging.exception("Caught exception")
                     print(exc_type, fname, exc_tb.tb_lineno)
                     pass
      
                 starttime = datetime.datetime.now()
      
             time.sleep(1)
      
      #except KeyboardInterrupt:
      #    GPIO.cleanup()
      #    dmx_stop()
      finally:
         print("cleanup")
      
      mirko@felicity:~/felicityBMSscript $
      
      

      Der Service ist so eingerichtet:

      mirko@felicity:/etc/systemd/system $ cat FelicityBMS.service
      [Unit]
      Description=hit service
      After=network-online.target
      
      [Service]
      ExecStart=/usr/bin/python /home/mirko/felicityBMSscript/BMSsnippet_iob_leon.py
      
      [Install]
      WantedBy=multi-user.target
      mirko@felicity:/etc/systemd/system $
      
      

      Jemand ne Idee was die Ursache sein kann das ich irgendwann x Python Prozesse aktiv habe und die Abfrage dann nicht mehr funktioniert?

      Thx

      BananaJoe Thomas Braun 3 Replies Last reply Reply Quote 0
      • BananaJoe
        BananaJoe Most Active @wendy2702 last edited by BananaJoe

        @wendy2702 sagte in Python prozess wird nach Zeit X mehrfach ausgeführt.:

        FelicityBMS.service

        kannst auch mal den Inhalt der FelicityBMS.service posten? ok stand ganz unten

        Ich habe auch diverse Python-Skripte als Dienst laufen, bei mir sieht die Service-Datei so aus:

        [Unit]
        Description=Zabbix Sender URL Service
        After=syslog.target
        
        [Service]
        Type=simple
        WorkingDirectory=/gpio/flask
        ExecStart=/gpio/flask/ZabbixSenderByURL.py
        SyslogIdentifier=zabbixsenderbyurl
        StandardOutput=syslog
        StandardError=syslog
        Restart=always
        RestartSec=3
        
        [Install]
        WantedBy=multi-user.target
        

        type=simple hast du nicht angegeben, sollte aber auch der Default wert sein.
        Mein Python-Skript ist ausführbar ( chmod +x ... ) weshalb ich den Interpreter nicht extra mit angeben muss.
        After=network-online.target sollte auch ok sein.

        Im Skript sehe ich auf anhieb auch nicht was einen mehrfachen Start auslösen sollte.

        wendy2702 1 Reply Last reply Reply Quote 0
        • Thomas Braun
          Thomas Braun Most Active @wendy2702 last edited by

          @wendy2702

          So aus dem Stehgreif würde ich behaupten, das hängt mit der fehlenden Angabe zum Restart zusammen.

          Setzt das mal auf always.

          wendy2702 1 Reply Last reply Reply Quote 0
          • wendy2702
            wendy2702 @BananaJoe last edited by

            @bananajoe hi und danke für deine Info.

            Ich passe den Service mal an und beobachte.

            Kann aber erst am Wochenende schauen da ich jetzt unterwegs bin.

            1 Reply Last reply Reply Quote 0
            • BananaJoe
              BananaJoe Most Active @wendy2702 last edited by

              @wendy2702 was beim Skript so beim mehrmaligen anschauen blöd sein könnte, ist das es beim Start eine MQTT Verbindung zum MQTT Broker aufbaut (Zeile 79 bis 83).
              Erhält das Skript den Stopp-Befehl, so wird die Verbindung wieder abgebaut.
              Ich sehe nichts was die Verbindung zur Laufzeit prüft, danach wird in der Hauptschleife nur noch gesendet.
              Ob das wirklich ein Problem ist, weis ich aber nicht (oder ob der paho.mqtt.client das händelt).

              wendy2702 1 Reply Last reply Reply Quote 0
              • wendy2702
                wendy2702 @Thomas Braun last edited by

                @thomas-braun sagte in Python prozess wird nach Zeit X mehrfach ausgeführt.:

                @wendy2702

                So aus dem Stehgreif würde ich behaupten, das hängt mit der fehlenden Angabe zum Restart zusammen.

                Setzt das mal auf always.

                Ok.

                Das hat @BananaJoe ja auch drin stehen.

                Mal meinen Sohn antriggern ob der das schnell ändern kann.

                1 Reply Last reply Reply Quote 0
                • wendy2702
                  wendy2702 @BananaJoe last edited by

                  @bananajoe sagte in Python prozess wird nach Zeit X mehrfach ausgeführt.:

                  @wendy2702 was beim Skript so beim mehrmaligen anschauen blöd sein könnte, ist das es beim Start eine MQTT Verbindung zum MQTT Broker aufbaut (Zeile 79 bis 83).
                  Erhält das Skript den Stopp-Befehl, so wird die Verbindung wieder abgebaut.
                  Ich sehe nichts was die Verbindung zur Laufzeit prüft, danach wird in der Hauptschleife nur noch gesendet.
                  Ob das wirklich ein Problem ist, weis ich aber nicht (oder ob der paho.mqtt.client das händelt).

                  Das habe ich dank KI auch erfahren aber kann mir nicht vorstellen das es zu mehreren Prozessen führen kann.

                  Bin aber auch kein Informatiker etc.

                  1 Reply Last reply Reply Quote 0
                  • wendy2702
                    wendy2702 last edited by

                    So,

                    Hatte vor einigen Tagen den Service geändert:

                    
                    Unit]
                    Description=Felicity Abfrage  service
                    After=network-online.target
                    
                    [Service]
                    Type=simple
                    ExecStart=/usr/bin/python /home/mirko/felicityBMSscript/BMSsnippet_iob_leon.py
                    SyslogIdentifier=felictyabfrage
                    StandardOutput=syslog
                    StandardError=syslog
                    Restart=always
                    
                    [Install]
                    WantedBy=multi-user.target
                    
                    
                    

                    Heute läuft der Python Prozeß wieder mehrfach.

                    Sieht hier noch wer einen Fehler oder hat einen anderen Tipp?

                    BananaJoe 1 Reply Last reply Reply Quote 0
                    • BananaJoe
                      BananaJoe Most Active @wendy2702 last edited by BananaJoe

                      @wendy2702 kannst du mal ein

                      /usr/bin/python --version
                      

                      aufrufen? Und ich hoffe da kommt nicht 2.7 ...

                      Und wenn der wieder "mehrfach" läuft, gib bitte diesen Befehl ein und poste hier die Ausgabe:

                      ps -aux |grep python
                      

                      und beim Service hänge unter das Restart dann auch noch diese Zeile:

                      RestartSec=30
                      

                      damit er ein wenig Pause macht vor einem Neustart.

                      Ich war schon drauf und dran das Skript anzupassen - aber ich könnte es bei mir ja nicht testen.
                      Blöd ist, das das Skript ja nicht wirklich auf Start/Stop-Anforderungen reagiert.

                      Hier hat jemand eine schöne Idee dafür vorgeschlagen: https://oxylabs.io/blog/python-script-service-guide
                      Bei der Lösung reagiert das Skript selbst auf die Anforderungen.
                      Meine Python-Dienste nutzen alle Flask, ich vermute das hat das schon eingebaut.

                      wendy2702 1 Reply Last reply Reply Quote 0
                      • wendy2702
                        wendy2702 @BananaJoe last edited by

                        @bananajoe Die Python Version ist:

                        Python 3.11.2
                        

                        Service werde ich erweitern und mir den Link mal anschauen.

                        Danke!

                        1 Reply Last reply Reply Quote 0
                        • wendy2702
                          wendy2702 last edited by

                          @bananajoe sagte in Python prozess wird nach Zeit X mehrfach ausgeführt.:

                          ps -aux |grep python

                          Jetzt dachte ich nach einfügen der Restart Zeit würde es funktionieren aber dann sehe ich heute wieder mehrere Prozesse.

                          @BananaJoe hier mal die gewünschte Ausgabe

                          mirko@felicity:~ $ ps -aux |grep python
                          root        1833  0.5  2.7 109996 25984 ?        Ssl  Mar04  31:55 /usr/bin/python /home/mirko/felicityBMSscript/BMSsnippet_iob_leon.py
                          mirko       2482  0.0  0.1   2320  1280 ?        Ss   Mar04   0:00 /bin/sh -c /usr/bin/python /home/mirko/felicityBMSscript/BMSsnippet_iob_leon.py
                          mirko       2483  0.5  2.7 109996 25996 ?        Sl   Mar04  28:54 /usr/bin/python /home/mirko/felicityBMSscript/BMSsnippet_iob_leon.py
                          mirko       4229  0.0  0.1   2320  1280 ?        Ss   Mar05   0:00 /bin/sh -c /usr/bin/python /home/mirko/felicityBMSscript/BMSsnippet_iob_leon.py
                          mirko       4230  0.4  2.6 109020 25044 ?        Sl   Mar05  20:35 /usr/bin/python /home/mirko/felicityBMSscript/BMSsnippet_iob_leon.py
                          mirko       5979  0.0  0.1   2320  1280 ?        Ss   Mar06   0:00 /bin/sh -c /usr/bin/python /home/mirko/felicityBMSscript/BMSsnippet_iob_leon.py
                          mirko       5980  0.4  2.6 108996 25032 ?        Sl   Mar06  12:39 /usr/bin/python /home/mirko/felicityBMSscript/BMSsnippet_iob_leon.py
                          mirko       7714  0.0  0.1   2320  1280 ?        Ss   Mar07   0:00 /bin/sh -c /usr/bin/python /home/mirko/felicityBMSscript/BMSsnippet_iob_leon.py
                          mirko       7715  0.4  2.6 108996 24892 ?        Sl   Mar07   5:21 /usr/bin/python /home/mirko/felicityBMSscript/BMSsnippet_iob_leon.py
                          mirko       9345  0.0  0.2   6088  1920 pts/0    S+   14:53   0:00 grep --color=auto python
                          
                          
                          BananaJoe 1 Reply Last reply Reply Quote 0
                          • BananaJoe
                            BananaJoe Most Active @wendy2702 last edited by

                            @wendy2702 der läuft aber ja 1x als root und 9x als mirko in 2 verschiedenen Varianten

                            Der als root ist vermutlich der richtige, der hat auch die niedrigste Prozessnummer.
                            Also du hast irgendwo noch etwas was weitere Instanzen startet auf 2 wegen.
                            Da iobroker nicht der Besitzer ist, der vermutlich nicht.

                            was steht denn in den Cronjobs von mirko?

                            crontab -e
                            
                            wendy2702 1 Reply Last reply Reply Quote 1
                            • wendy2702
                              wendy2702 @BananaJoe last edited by

                              @bananajoe Bist mein Held für heute.

                              Es gab von den ersten Versuchen noch einen crontab den ich komplett vergessen hatte.

                              Denke mit löschen des Eintrags sollte mein Problem jetzt gelöst sein.

                              1 Reply Last reply Reply Quote 0
                              • First post
                                Last post

                              Support us

                              ioBroker
                              Community Adapters
                              Donate

                              723
                              Online

                              31.7k
                              Users

                              79.7k
                              Topics

                              1.3m
                              Posts

                              3
                              13
                              359
                              Loading More Posts
                              • Oldest to Newest
                              • Newest to Oldest
                              • Most Votes
                              Reply
                              • Reply as topic
                              Log in to reply
                              Community
                              Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                              The ioBroker Community 2014-2023
                              logo