Würde gerne eine Lauftext erstellen.

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Wolle_wtal
User
Beiträge: 15
Registriert: Donnerstag 28. Februar 2019, 13:02

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.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

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?
Wolle_wtal
User
Beiträge: 15
Registriert: Donnerstag 28. Februar 2019, 13:02

Ganz ehrlich nein, habe das self nur eingefügt, weil pycharm das bemängelt hat.

Gruß und danke erstmal, muss das jetzt mal testen.
Sirius3
User
Beiträge: 18269
Registriert: Sonntag 21. Oktober 2012, 17:20

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]
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

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.
Wolle_wtal
User
Beiträge: 15
Registriert: Donnerstag 28. Februar 2019, 13:02

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)



__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

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.
Wolle_wtal
User
Beiträge: 15
Registriert: Donnerstag 28. Februar 2019, 13:02

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
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

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?
Wolle_wtal
User
Beiträge: 15
Registriert: Donnerstag 28. Februar 2019, 13:02

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.
Benutzeravatar
__blackjack__
User
Beiträge: 14040
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Wolle_wtal
User
Beiträge: 15
Registriert: Donnerstag 28. Februar 2019, 13:02

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.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

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.
Wolle_wtal
User
Beiträge: 15
Registriert: Donnerstag 28. Februar 2019, 13:02

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
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

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.
Sirius3
User
Beiträge: 18269
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: „gut ist” ist nur gut, wenn dieses Framework auch mit Threads arbeiten kann. Davon sollte man nicht ohne weiteres ausgehen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Gehe ich nicht. Der TE ist sich jedoch sehr sicher & hat die Frage nach Timern ignoriert 🤷🏼‍♂️
Benutzeravatar
__blackjack__
User
Beiträge: 14040
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Antworten