Seite 1 von 1

Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 15:00
von Wolle_wtal
Hallo zusammen,

ich würde gerne einen Lauftext erstellen.

Der Zugehörige Text steht in der Variable "Ausgabe".
Ich habe hier im Forum folgendes gefunden:

Code: Alles auswählen

def iter_slices(self, text, slice_length):
                 text = deque(text)
                 while True:
                      yield ''.join(islice(text, slice_length))
                      text.rotate(-1)
                      
Den Aufruf habe ich bisher so probiert:

Code: Alles auswählen

self.iter_slices(Ausgabe, 10)
Habe

Code: Alles auswählen

import collections
import itertools
eingebunden.

Das ganze soll am Ende auf

Code: Alles auswählen

self._set_output_value(self.PIN_O_CMGSTRINGOUTPUT, Text)
ausgegeben werden.

Aber ich weiß einfach nicht, welcher teil des obigen Codes mir eine Ausgabe erzeugt.

Daher bitte ich um eure Hilfe, wenn es geht mit Erklärung für mein Verständnis.

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 15:06
von __deets__
Der Generator (das Ding mit dem yield) erzeugt eine Rueckgabe mit dem gescrollten Text. Du musst sowohl den Generator selbst als auch die Rueckgabe verwerten:

Code: Alles auswählen

from collections import deque
from itertools import islice
import time

def iter_slices(text, slice_length):
    text = deque(text)
    while True:
        yield ''.join(islice(text, slice_length))
        text.rotate(-1)

def main():
    gen = iter_slices("hallo welt ", 10)
    while True:
        time.sleep(.1)
        print(next(gen))

if __name__ == '__main__':
    main()
Und in deinem iter_silces hast du einfach ein nutzloses self eingestreut. Weisst du, wozu self da ist?

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 15:15
von Wolle_wtal
Ganz ehrlich nein, habe das self nur eingefügt, weil pycharm das bemängelt hat.

Gruß und danke erstmal, muss das jetzt mal testen.

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 15:21
von Sirius3
Bei einer `deque` braucht man eigentlich auch kein islice.

Code: Alles auswählen

def iter_slices(text, slice_length):
    text = deque(text)
    while True:
        yield ''.join(text[:slice_length])
        text.rotate(-1)
Und wenn text nicht all zu groß ist, ist es effizienter, direkt mit Strings zu arbeiten:

Code: Alles auswählen

from itertools import count

def iter_slices(text, slice_length):
    text *= 2
    for index in count():
        index %= len(text)//2
        yield text[index: index+slice_length]

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 15:22
von __deets__
Das hat es dann wahrscheinlich auch zu recht getan, das liegt aber wiederum daran, wo du den Code hinkopiert hast. Und das ist ja nun nicht einfach egal. Da der Generator sonst keine Abhaengigkeiten hat, sollte er einfach auf Modulebene stehen, und gut ist.

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 15:36
von Wolle_wtal
Hab das ganze mal versucht, bekomme es nicht hin.
Ich liefer mal den ganzen code.

Nicht über den commentblock wundern. Der wird von einem Generator erzeugt, liefert auch nur das Grundgerüst für die Logik, und darf nicht geändert werden, weil dahinter ein Logikmodul steckt was am Ende alles abarbeitet. Der untere Teil darf und muss manuell erstell werden.

Code: Alles auswählen

# coding: UTF-8
import collections
import itertools
import time

##!!!!##################################################################################################
#### Own written code can be placed above this commentblock . Do not change or delete commentblock! ####
########################################################################################################
##** Code created by generator - DO NOT CHANGE! **##

class Alarmanlage10001(hsl20_3.BaseModule):

    def __init__(self, homeserver_context):
        hsl20_3.BaseModule.__init__(self, homeserver_context, "Alarmanlage")
        self.FRAMEWORK = self._get_framework()
        self.LOGGER = self._get_logger(hsl20_3.LOGGING_NONE,())
        self.PIN_I_CMELDEBEREICH=1
        self.PIN_I_CINTERNSCHARF=2
        self.PIN_I_CEXTERNSCHARF=3
        self.PIN_I_CUEBERFALL=4
        self.PIN_I_CTESTALARM=5
        self.PIN_I_CRESET=6
        self.PIN_I_CMGSTRINGINPUT=7
        self.PIN_I_CSCHAERFENVERZOEGERUNGEINGANG=8
        self.PIN_I_CALARMVERZOEGERUNGEINGANG=9
        self.PIN_I_CEXPORT=10
        self.PIN_I_CMG1NAME=11
        self.PIN_I_CMG1INTERN=12
        self.PIN_I_CMG1EXTERN=13
        self.PIN_I_CMG1ALARM=14
        self.PIN_I_CMG2NAME=15
        self.PIN_I_CMG2INTERN=16
        self.PIN_I_CMG2EXTERN=17
        self.PIN_I_CMG2ALARM=18
        self.PIN_I_CMG3NAME=19
        self.PIN_I_CMG3INTERN=20
        self.PIN_I_CMG3EXTERN=21
        self.PIN_I_CMG3ALARM=22
        self.PIN_I_CMG4NAME=23
        self.PIN_I_CMG4INTERN=24
        self.PIN_I_CMG4EXTERN=25
        self.PIN_I_CMG4ALARM=26
        self.PIN_I_CMG5NAME=27
        self.PIN_I_CMG5INTERN=28
        self.PIN_I_CMG5EXTERN=29
        self.PIN_I_CMG5ALARM=30
        self.PIN_I_CMG6NAME=31
        self.PIN_I_CMG6INTERN=32
        self.PIN_I_CMG6EXTERN=33
        self.PIN_I_CMG6ALARM=34
        self.PIN_I_CMG7NAME=35
        self.PIN_I_CMG7INTERN=36
        self.PIN_I_CMG7EXTERN=37
        self.PIN_I_CMG7ALARM=38
        self.PIN_I_CMG8NAME=39
        self.PIN_I_CMG8INTERN=40
        self.PIN_I_CMG8EXTERN=41
        self.PIN_I_CMG8ALARM=42
        self.PIN_I_CMG9NAME=43
        self.PIN_I_CMG9INTERN=44
        self.PIN_I_CMG9EXTERN=45
        self.PIN_I_CMG9ALARM=46
        self.PIN_I_CMG10NAME=47
        self.PIN_I_CMG10INTERN=48
        self.PIN_I_CMG10EXTERN=49
        self.PIN_I_CMG10ALARM=50
        self.PIN_I_CMG11NAME=51
        self.PIN_I_CMG11INTERN=52
        self.PIN_I_CMG11EXTERN=53
        self.PIN_I_CMG11ALARM=54
        self.PIN_I_CMG12NAME=55
        self.PIN_I_CMG12INTERN=56
        self.PIN_I_CMG12EXTERN=57
        self.PIN_I_CMG12ALARM=58
        self.PIN_I_CMG13NAME=59
        self.PIN_I_CMG13INTERN=60
        self.PIN_I_CMG13EXTERN=61
        self.PIN_I_CMG13ALARM=62
        self.PIN_I_CMG14NAME=63
        self.PIN_I_CMG14INTERN=64
        self.PIN_I_CMG14EXTERN=65
        self.PIN_I_CMG14ALARM=66
        self.PIN_I_CMG15NAME=67
        self.PIN_I_CMG15INTERN=68
        self.PIN_I_CMG15EXTERN=69
        self.PIN_I_CMG15ALARM=70
        self.PIN_I_CMG16NAME=71
        self.PIN_I_CMG16INTERN=72
        self.PIN_I_CMG16EXTERN=73
        self.PIN_I_CMG16ALARM=74
        self.PIN_I_CMG17NAME=75
        self.PIN_I_CMG17INTERN=76
        self.PIN_I_CMG17EXTERN=77
        self.PIN_I_CMG17ALARM=78
        self.PIN_I_CMG18NAME=79
        self.PIN_I_CMG18INTERN=80
        self.PIN_I_CMG18EXTERN=81
        self.PIN_I_CMG18ALARM=82
        self.PIN_I_CMG19NAME=83
        self.PIN_I_CMG19INTERN=84
        self.PIN_I_CMG19EXTERN=85
        self.PIN_I_CMG19ALARM=86
        self.PIN_I_CMG20NAME=87
        self.PIN_I_CMG20INTERN=88
        self.PIN_I_CMG20EXTERN=89
        self.PIN_I_CMG20ALARM=90
        self.PIN_O_CEXTERNBEREIT=1
        self.PIN_O_CINTERNBEREIT=2
        self.PIN_O_CEXTERNSCHARFSTATUS=3
        self.PIN_O_CINTERNSCHARFSTATUS=4
        self.PIN_O_CSCHARFVERZOEGERUNG=5
        self.PIN_O_CUNSCHARFVERZOEGERUNG=6
        self.PIN_O_CMGSTRINGOUTPUT=7
        self.PIN_O_CALARM=8
        self.REM_V_BEZ=1
        self.FRAMEWORK._run_in_context_thread(self.on_init)

####################################################################################################
#### Own written code can be placed after this commentblock . Do not change or delete commentblock! ####
####################################################################################################

    def on_init(self):
        pass

    def on_input_value(self, index, value):
        i = 0
        eingang = 0
        Ausgabe = ""
        while i < 20:
            eingang = self._get_input_value(getattr(self, 'PIN_I_CMG{}ALARM'.format(i+1)))
            if eingang > 0:
                Ausgabe += self._get_input_value(getattr(self, 'PIN_I_CMG{}NAME'.format(i+1))) + ', '
            i += 1
        
        gen = iter_slices(Ausgabe, 5)
        while True:
            time.sleep(.1)
            self._set_output_value(self.PIN_O_CMGSTRINGOUTPUT, next(gen))

    
    def iter_slices(text, slice_length):
        text = deque(text)
        while True:
            yield ''.join(islice(text, slice_length))
            text.rotate(-1)




Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 15:41
von __deets__
So geht's nicht. Zum einen gehoert iter_slices *OHNE* self auf Moduleben, nicht in die Klasse. Zum anderen darfst du garantiert keine Schleife in deinem on_input_value haben. Die Erzeugung des Generators sollte am besten wohl in die on_init, und nur das abholen des naechsten Wertes gehoert in die on_input_value.

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 15:50
von Wolle_wtal
In den meisten Fällen mag dass alles stimmen, hier ist das aber etwas anders zu verstehen. Eine kurze Erklärung dazu.

Bei dem ganzen hier handelt es sich um einen Logikbaustein für einen Homeserver der Firma Gira. Dieses Gerät gibt die Möglichkeit eigene Logiken zu definieren. Dahinter steckt ein von Gira eigenes SDK.

on_init ist hier eine Feste reservierte Funktion die den Neustarts des Homeservers meint. Es wird nur einmalig ausgeführt wenn der Server neu gestartet wird sonnst macht diese on_init nichts.

Da mein Baustein nichts bei Systemstart machen soll, ist hier auch nichts reinzuschreiben.

on_input_value ist ebenfalls eine reservierte Geschichte. Diese wird immer dann ausgelöst wenn an egal welchem Eingang des Logikbausteins ein Wert empfangen wird. Konkret immer dann wenn sich an einem der im oberen Teil befindlichen PIN_I etwas ändert und zwar zur Laufzeit.

Aus diesem Grunde muss die Schleife auch in diesem Teil liegen, da zur Laufzeit eine Änderung Eintritt und dann der ganze Prozess in Gang gesetzt wird.

Über Sinn oder Unsinn kann man bestimmt streiten, allerdings führt das zu nichts, weil alles andere in Zusammenhang mit dem Homeserver nicht funktioniert.

Gruß, Wolle

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 16:29
von __deets__
Ich bin mir recht sicher, dasse eine Scheife NICHT gehen wird, denn dann wird fuer die Laufzeit deiner Laufschrift nichts anderes mehr verarbeitet. Womit Sinn und Zweck einer Alarmanaleg ggf. auf der Kippe stehen. Kann dieses System von dir Timer?

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 18:29
von Wolle_wtal
Mit der Schleife hast du natürlich recht.

In dem Fall ist das allerdings nur die Reaktion auf einen Input. Input Ist in diesem Fall wenn ein Fenster geöffnet wird, werden alle Meldegruppen kontrolliert und in der While-Schleife ein String mit den Bezeichnungen der Meldegruppen gebildet.

Soweit funktioniert das auch Perfekt. In Ausgabe steht dann der gebildete String und dieser soll halt wieder ausgegeben werden.

Leider habe ich in der Visualisierung des Servers nur eine Zeile für die Anzeige und diese hat natürlich auf einem Handydisplay eine sehr begrenzte Anzahl an Zeichen.

Aus diesem Grund habe ich halt nach einer Laufschrift gesucht. Mir würde auch reichen wenn immer 10 vielleicht auch 15 Zeichen des Strings im Sekunden Wechsel angezeigt werden und das nach Möglichkeit solange bis alle Alarmeingänge wieder 0 sind.

Viel mehr muss da erstmal nicht passieren. Um den Rest kümmert sich der Server selbst. Der Durchlauf der Schleife ist ja im Null Komma nix abgearbeitet und dann passiert vorerst nichts mehr bis zur nächsten Eingabe.

Die eigentliche Laufschrift soll später in einem eigenen Thread ausgeführt werden, damit die Hauptfunktion nicht eingeschränkt wird. Das Problem ist, dass ich das mit der Laufschrift als ersten Step realisieren will. Bis zum endgültigen Baustein ist es noch ein langer Weg, auch des Verstehens. Threads sind im Baustein möglich.

Gruß und vielen Dank für die Hilfestellungen.

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 19:07
von __blackjack__
@Wolle_wtal: Der Durchlauf einer Endlosschleife ist nicht in Null Komma Nix abgearbeitet – die läuft unendlich lange.

Der Code für die Erstellung von Ausgabe sollte eine ``for``-Schleife und keine ``while``-Schleife sein.

`eingang` vorher mit einer 0 zu initialisieren die nie irgendwo verwendet wird, macht keinen Sinn.

Man baut auch keine Zeichenkette mit wiederholtem ``+=`` auf. Das ist ineffizient. Idiomatischerweise sammelt man die Einzelteile in einer Liste und setzt die Elemente dann am Ende mit der `join()`-Methode auf Zeichenketten zusammen.

Ich würde mir ja auch in der `on_init()` aus den ganzen PIN_*-Attributen was basteln was einfacher und lesbarer zu verwenden ist als dieses `self._get_input_value(getattr(self, 'PIN_I_CMG{}ALARM'.format(i+1)))`. Das ist eine grauenhafte API.

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 20:08
von Wolle_wtal
Ob es eine for oder while Schleife ist, ist mir Wurst. Klappt für meinen Zweck beides. Kann ich ja schnell umbauen. Der String wird am Ende der gleiche sein.

Das += ist für meinen Zweck genau richtig und auch nicht Bestandteil meiner Frage. Allerdings schaue ich mir das zu Lernzwecken gerne einmal an.

Alles was man in on_init macht, wird nur 1 einziges Mal beim physischen Neustart des Servers ausgeführt und danach nie wieder. Das api Model mag Mist sein, allerdings kann man daran nix ändern. Das ist es was der Hersteller des Systems zur Verfügung stellt und für den Zweck reicht das auch. Das Problem ist das diese Bausteine nur ein kleiner Abschnitt einer komplexen Logik sind und Mann es erst richtig versteht wenn man die Homeserverlogik generell kennt, dass ist aber hier nicht erklärbar. Leider hat man auf gewisse Dinge keinen Einfluss.

Übrigens zum Verständniss auch wenn es komisch ist. Jeder PIN_I kann sich zur Laufzeit ändern und zwar immer dann wenn aus einem anderen Bereich der Logik (nicht Bestandteil dieses Bausteins) ein Signal auf einen PIN_I getriggert wird. Das würde im On_Init nicht verarbeitet.

Also. Ich benötige erstmal nur eine Möglichkeit, wie ich das mit der Laufschrift realisiere und zwar mit den Möglichkeiten die mir gegeben sind.

Gruß und Danke.

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 20:26
von __deets__
Na wenn du Threads hast, dann nimm halt einen. Was hält dich auf? Das der Generator nicht als Methode in die Klasse gehört haben wir ja auch ein paar mal erwähnt. Pack das alles in eine thread und gut ist.

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 20:41
von Wolle_wtal
Na den Thread bekomme ich gestartet, aber ich habe noch immer nicht verstanden wie ich die Laufschrift erstelle ^^. Das ist mein Problem, das sage ich doch die ganze Zeit.

Gruß, Wolle

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 20:52
von __deets__
Ich habe dir ein lauffähiges Beispiel gezeigt, aus dem klar wird, wie man den Laufschrift code nutzt. Kann so auch in einen Thread gepackt werden. Was ist dir unklar?

Unsere Anmerkungen hast du beiseite gewischt mit “ist bei mir aber anders”. Dein Tool hat hier keiner. Die Leistung den funktionierenden Code auf deine spezielle Umgebung abzubilden kann dir also keiner abnehmen.

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 21:42
von Sirius3
@__deets__: „gut ist” ist nur gut, wenn dieses Framework auch mit Threads arbeiten kann. Davon sollte man nicht ohne weiteres ausgehen.

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 21:44
von __deets__
Gehe ich nicht. Der TE ist sich jedoch sehr sicher & hat die Frage nach Timern ignoriert 🤷🏼‍♂️

Re: Würde gerne eine Lauftext erstellen.

Verfasst: Montag 6. Mai 2019, 22:03
von __blackjack__
@Wolle_wtal: Das die `on_init()` genau einmal aufgerufen wird, haben wir glaube ich alle verstanden. Weiss nicht warum Du das noch mal schreibst. Aus den ganzen PIN_*-Konstanten eine sinnvollere, weniger schmerzhafte API zu basteln würde genau in diese Methode gehören, denn das muss man ja nur einmal am Anfang machen. Es get ja auch nicht darum die Werte dieser `PIN_I_*` dort abzufragen, sondern dafür zu sorgen, das man das in anderen Methoden dann einfacher und verständlicher machen kann.

Ergänzend zu __deets__: Ich glaube auch nicht das bei dir alles anders ist. Du denkst bloss das wäre es. Klar gibt es ein paar Einschränkungen durch die Software die Du da benutzt, Du reagierst aber irgendwie Reflexhaft auf alles mit „ich kann das nicht machen“ oder „ich muss das so machen“ mit Hinweis auf die Software. Siehe den ersten Absatz dieser Antwort.

Zur Laufschrift: Mach das als Thread der in der `on_init()` gestartet wird – und ja wirklich dort! Und der über eine `Queue` immer wenn sich etwas an der Nachricht ändert, die geänderte Nachricht als Laufschrift übernimmt.