Ankündigung

Einklappen
Keine Ankündigung bisher.

Logik mit verschiedenen (abgeleiteten) Klassen funktioniert nicht

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Logik mit verschiedenen (abgeleiteten) Klassen funktioniert nicht

    Hallo!

    Scheinbar sind meine smarthome.py Kenntnisse ein wenig eingerostet. Zumindest kriege ich eine "komplexere" Logik nicht hin und finde auch in der der Doku nichts erhellendes.

    Idee ist es, verschiedene Logiken relativ übersichtlich als Zustandsmaschine zu beschreiben. Hier als Beispiel von einer Raffstore-Steuerung. Basis-Klassen für "StateMachine" und "State", davon abgeleitete Klassen "RaffstoreSteuerung" bzw. "Tag"/"Nacht".

    Code:
    #!/usr/bin/env python3
    
    class StateMachine:
        def __init__(self, initialState):
            self.currentState = initialState
            self.currentState.run()
    
        def runAll(self, inputs):
            for i in inputs:
                newState = self.currentState.next(i)
                if (newState != self.currentState):
                    logger.info("Transition \"{0} -> {1}\"".format(self.currentState, newState))
                    self.currentState = newState
                self.currentState.run()
    
    class State:
        def __init__(self, stateMachine):
            assert issubclass(type(stateMachine), StateMachine)
            self.stateMachine = stateMachine
    
        def __str__(self):
            return self.__class__.__name__
    
        def run(self):
            assert 0, "run not implemented"
    
        def next(self, input):
            assert 0, "next not implemented"
    
    
    class RaffstoreSteuerung(StateMachine):
        def __init__(self, sh):
            # Initial state
            self.nacht = Nacht(self)
            self.tag = Tag(self)
            self.sh = sh
            super().__init__(self.nacht)
    
    
    class Nacht(State):
        def run(self):
            pass
    
        def next(self, input):
            return self.stateMachine.tag
    
    class Tag(State):
        def run(self):
            pass
    
        def next(self, input):
            return self.stateMachine.nacht
    
    basepath = "Wohnzimmer.Raffstore.Automatik"
    baseitem = sh.return_item(basepath)
    
    if not hasattr(baseitem, "rs"):
        baseitem.rs = RaffstoreSteuerung(sh)
    In der normalen Python3-Console funktioniert der Code (bzw. mit geringen Anpassungen da außerhalb der dh.py Umgebung), in sh.py wird nocht der Konstruktor von "RaffstoreSteuerung" aufgerufen, jedoch findet dieser die Klasse "Nacht" nicht. Ich schätze, dass dies an dem Kompilieren der Logik liegt oder ähnlich.

    Fehlermeldung:

    Code:
    2016-12-18  18:32:33 ERROR    raffstoren_steuerung_wohnzimmer Logic: raffstoren_steuerung_wohnzimmer, File: /usr/local/smarthome/logics/raffstoren_steuerung_wohnzimmer.py, Line: 34, Method: __init__, Exception: name 'Nacht' is not defined
    Traceback (most recent call last):
      File "/usr/local/smarthome/lib/scheduler.py", line 355, in _task
        exec(obj.bytecode)
      File "/usr/local/smarthome/logics/raffstoren_steuerung_wohnzimmer.py", line 58, in <module>
        baseitem.rs = RaffstoreSteuerung(sh)
      File "/usr/local/smarthome/logics/raffstoren_steuerung_wohnzimmer.py", line 34, in __init__
        self.nacht = Nacht(self)
    NameError: name 'Nacht' is not defined
    Jemand eine Idee? (smarthomeNG, aktueller develop)

    Grüße
    Robert

    #2
    Hast du schon versucht Nacht und Tag vor
    RaffstoreSteuerung zu verschieben? Von der Reihenfolge her kann ich mir vorstellen, dass
    RaffstoreSteuerung Nacht und Tag nicht kennt, da sie erst nach dieser Klasse definiert werden.
    Gruß
    Christian

    Kommentar


      #3
      Hallo Christian,

      danke für Deine Antwort. Ja, umsortieren habe ich als C-Programmierer auch schon versucht. Bringt leider nichts und im Netz steht - ich kann es jetzt nicht im Wortlaut wiedergeben - das Python das nicht braucht. Zudem es ja auch direkt mit dem Interpreter ausgeführt problemlos funktioniert. Ich befürchte das "compile" in der logic.py ändert hier etwas bzw. aufgrund des Kontextes funktioniert es nicht.

      Grüße
      Robert

      Kommentar


        #4
        Hi Robert,
        ich baue das mal nach. Ich kann mir vorstellen dass es Probleme mit den Klassen gibt.


        Gruß Christian

        Kommentar


          #5
          Hallo Christian,

          danke dir!

          Ich konnte es heute beheben, indem ich die Klassen Tag, Nacht und StateMachine mit einem "global" verziere. Nur der genaue Grund ist mir noch nicht klar, liegt aber wohl eben an den global/local scope im exec...

          Grüße
          Robert

          Kommentar


            #6
            Ich glaube das liegt an dem Compile, da werde ich noch nachforschen weil mich das interessiert.
            Ich habe noch einen anderen Workaround:
            Die Klassen in eine separate Datei "logics/statemachine.py":
            Code:
            #!/usr/bin/env python3
            import logging
            logger = logging.getLogger(__name__)
            class StateMachine:
                def __init__(self, initialState):
                    self.currentState = initialState
                    self.currentState.run()
                    def runAll(self, inputs):
                        for i in inputs:
                            newState = self.currentState.next(i)
                            if (newState != self.currentState):
                                logger.info("Transition \"{0} -> {1}\"".format(self.currentState, newState))
                                self.currentState = newState
                            self.currentState.run()
            
            class RaffstoreSteuerung(StateMachine):
                def __init__(self, sh):
                    # Initial state
                    self.nacht = Nacht(self)
                    self.tag = Tag(self)
                    self.sh = sh
                    super().__init__(self.nacht)
            
            
            
            class State():
                def __init__(self, stateMachine):
                    assert issubclass(type(stateMachine), StateMachine)
                    self.stateMachine = stateMachine
            
                def __str__(self):
                    return self.__class__.__name__
            
                def run(self):
                    assert 0, "run not implemented"
            
                def next(self, input):
                    assert 0, "next not implemented"
            class Nacht(State):
                def run(self):
                    pass
            
                def next(self, input):
                    return self.stateMachine.tag
            
            class Tag(State):
                def run(self):
                    pass
            
                def next(self, input):
                    return self.stateMachine.nacht
            und in die Logik dann:
            Code:
            #!/usr/bin/env python3
            import logics.statemachine
            
            basepath = "Wohnzimmer.Raffstore.Automatik"
            baseitem = sh.return_item(basepath)
            if not hasattr(baseitem, "rs"):
                baseitem.rs = logics.statemachine.RaffstoreSteuerung(sh)
            Hat den Vorteil, dass man die Klassen noch in anderen Logiken verwenden kann.

            Gruß
            Christian
            Zuletzt geändert von cmalo; 20.12.2016, 23:26.

            Kommentar

            Lädt...
            X