Win_Info - Raspberry Gadget

  • Die Überschrift ist vielleicht nicht so gut, mir fiel aber (noch) nichts besseres ein... :shy:


    Ähnlich wie mein "RPi_Info - Windows Gadget", um System-Informationen des RaspberryPi's auf dem Windows-Desktop anzuzeigen, habe ich versucht sowas auch andersherum umzusetzen: System-Informationen eines Windows-PC's auf dem RaspberryPi-Desktop anzeigen.

    Die Entwicklung bzw genaue Details findet ihr im Thread von derveganemetzger: Ressourcenmonitor

    Ich hab mich dazu entschieden Windows Management Instrumentation (WMI) zu verwenden. Auf dem Windows-PC müssen 2 Programme laufen:
    - OpenHardwareMonitor ... was die nötigen Sensoren ausliest und ins WMI stellt.
    - wmi_server.py ... ein Python Script was die Informationen aus dem WMI ausließt und via Socket verschicken kann.


    Installation Windows:

    Open Hardware Monitor installieren & starten. "Run On Windows Startup" und die obersten beiden, in den Options einstellen ;)

    Ich empfehle folgendes Python für Windows zu installieren: python-3.5.3-amd64.exe ... Achtet darauf "Add Python to PATH" anzuwählen (ich empfehle "Customize installation"). Es geht natürlich auch eine 32bit Version von Python.

    Anschließend "cmd" als Administrator ausführen (Start => Alle Programme => Zubehör => rechtsklick auf Eingabeaufforderung und "Als Administrator ausführen") und folgende Python Module installieren:

    Code
    pip install wmi win32core pypiwin32

    (Die Eingabeaufforderung erst noch offen lassen, da kommen ggf noch ein paar Befehle rein ;))


    Nun käme der schwierige Teil beziehungsweise gibt es mehrere Möglichkeiten... Nämlich um das Python Script ebenfalls "Run On Windows Startup" auszuführen. Welche Möglichkeit ihr nehmt ist relativ egal, manche sind umständlicher andere nicht - ich leg mich hier nicht auf eine fest, entscheidet selbst.

    1.Möglichkeit => Klassisches Autostart:

    Spoiler anzeigen


    Hierbei legt man ein sog. Shortcut also eine Verknüpfung in das "Autostart" Verzeichnis von Windows an und lässt das Script mithilfe von "pythonw.exe" ausführen.
    Bei Windows 7 ist das "Autostart" Verzeichnis versteckt:

    Code
    C:\Users\USER\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\


    USER mit eurem Benutzernamen ersetzen

    Ihr könnt diese Adresse/Pfad in den Windows-Explorer oben rein pasten ohne die Ordneroptionen ändern zu müssen (Versteckte Dateien und Ordner)

    Beispielsweise habt ihr das Python Script im Verzeichnis "Eigene Dokumente" abgelegt - Wo die Datei liegt ist aber letztlich egal.
    Dann macht ihr auf die Datei ein Rechtsklick und wählt "Verknüpfung erstellen" aus.
    Dann benenne ich oftmals die Datei um und schneide das " - Verknüpfung" raus... Sieht besser aus.
    Anschließend macht ihr auf die Verknüpfung einen Rechtsklick und wählt "Eigenschaften" aus.
    Im Feld "Ziel" fügt ihr jetzt an den Anfang "pythonw.exe " ein, mit Leerzeichen. In dem Feld müsste dann also zB folgendes stehen:

    Code
    pythonw.exe C:\Users\x\Documents\wmi_server.py


    Sind Leerzeichen im Pfad enthalten dann mit " umschließen.
    Mit OK bestätigen.
    Die Verknüpfung verschiebt ihr dann in besagtes "Autostart" Verzeichnis. Fertig.

    Nachteil bei dieser Methode:
    Im 'Task Manager' taucht nur ein "pythonw.exe" Prozess auf. Habt ihr mehrere Python Scripts über pythonw am laufen könnt ihr die nicht auseinander halten.

    2.Möglichkeit => Run As Service:

    Spoiler anzeigen


    Hierfür bedient man sich eines zusätzlichen Programms: https://sourceforge.net/projects/runasservice/
    WICHTIG: "RunAsSvc.exe" wird hierfür permanent benötigt. Legt euch das Tool also in ein sicheres Verzeichnis wo es überdauern kann. Wird es gelöscht funktioniert diese Methode nicht mehr!

    Zunächst muss das Python Script aber erst in eine Executable (*.exe) umgewandelt werden, beziehungsweise werden alle nötigen Sachen wie Module usw in die exe mit rein gepackt sodass die exe auch auf Systemen ausgeführt werden kann wo kein Python installiert ist.
    Um das zu erreichen bevorzuge ich pyinstaller:

    Code
    pip install pyinstaller

    Anschließend in der Eingabeaufforderung folgendes ausführen:
    (zuvor ins entsprechende Verzeichnis wechseln)

    Code
    pyinstaller --noconsole -F wmi_server.py

    War das erfolgreich wurde eine wmi_server.exe im Unterverzeichnis "dist" erstellt. Das Arbeitsverzeichnis "build" kann man gefahrlos löschen.
    Datei eine Ebene höher verschieben und dann kann auch "dist" gelöscht werden.

    Nun kommt das eingangs erwähnte Tool "RunAsService" zum Einsatz... Rechtsklick auf "RunAsSvc.exe", als Administrator ausführen und die Felder wie folgt ausfüllen:
    - Dienstname: wmi_python_server
    - Beschreibung: wmi_python_server
    - Pfad zur Exe-Datei: ... navigiert zu eurer wmi_server.exe ...
    - Parameter:
    - Arbeitsverzeichnis: ... navigiert in das Verzeichnis eurer wmi_server.exe ...

    Anschließend mit OK bestätigen.

    Wer das verifizieren will kann das in der Verwaltung überprüfen: Start => Systemsteuerung => Verwaltung => Dienste. Ganz unten müsste dann der Dienstname gelistet werden.

    Wer den Dienst wieder löschen will gibt in der Eingabeaufforderung das ein:

    Code
    sc delete wmi_python_server


    Alternativ den Dienst aus der Registry löschen und anschließend rebooten, aber das ist mit Vorsicht zu genießen!
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services ... einer der {....} Verzeichnisse, müsst ihr selber rausfinden.

    Die beiden Möglichkeiten können auch vermischt werden (exe in "Startup" ablegen). Ich bin mir sicher das es auch noch weitere Möglichkeiten gibt :shy:

    wmi_server.py => https://slexy.org/view/s2fWHkifxo

    Spoiler anzeigen


    So weit so gut... Nun folgt der Teil an dem ich noch zu knabbern habe und Grund ist wieso ich diesen Thread in "laufende Projekte" erstellt habe: die GUI
    Für die GUI verwende ich Tkinter. Zur Darstellung möchte ich mich am "Open Hardware Monitor" orientieren und nutze daher ttk.Treeview()

    Was bisher problemlos funktioniert ist der Verbindungsaufbau und das Abrufen der Daten - ist ja auch eigentlich nicht weiter schwer...
    Allerdings stehe ich aktuell ein wenig auf dem Schlauch wie ich die Staffelung/Gruppierung der Daten verarbeite sodass zum Beispiel alle "Load" unter diesem node aufgelistet werden, aber nicht mehrere nodes "Load" eingefügt werden...
    Auch diese Baumansicht sieht noch längst nicht so aus wie ich mir das vorgestellt habe, derzeit steht einfach alles untereinander...
    Es werden auch bei jedem 'update_interval' nur neue Daten hinzugefügt, keine vorhanden gelöscht oder schlicht nur updated.
    Und zu guter letzt will die Scrollbar nicht so wie ich :X


    Vielleicht kann mir hier jemand auf die Sprünge helfen? :daumendreh2:


    Achja: Durch Doppelklick auf zB eure CPU klappt dieser Teil auf und so sieht das ganze derzeit aus:

    GUI => https://slexy.org/view/s2290gd9nO

    Spoiler anzeigen


    [code=php]
    #!/usr/bin/python3
    #
    # Creator: meigrafd
    # Copyright (C) 2017 by meiraspi@gmail.com published under the Creative Commons License (BY-NC-SA)
    #
    import sys
    import json
    import socket
    import select
    import struct
    import tkinter as tk
    import tkinter.ttk as ttk


    class GUI(object):
    def __init__(self, resolution="640x480", host='127.0.0.1', port=7060, timeout=5, interval=5000):
    self.host = host
    self.port = port
    self.gui_resolution = resolution
    self.timeout = timeout
    self.running = False
    self.update_interval = interval #ms
    self.master = tk.Tk()
    #self.master.geometry(self.gui_resolution)
    self.master.protocol("WM_DELETE_WINDOW", self.quit)
    self.main()


    # https://stackoverflow.com/q/32051780/2641799
    def main(self):
    frame = ttk.Frame(self.master)
    frame.pack()

    header = ['Sensor', 'Value', 'Min', 'Max']
    self.tree = ttk.Treeview(frame, columns=header, show='headings')

    # setup column headings
    self.tree.heading('#1', text='Sensor', anchor=tk.W)
    self.tree.heading('Value', text='Value', anchor=tk.W)
    self.tree.column('Value', stretch=0, width=70)
    self.tree.heading('Min', text='Min', anchor=tk.W)
    self.tree.column('Min', stretch=0, width=70)
    self.tree.heading('Max', text='Max', anchor=tk.W)
    self.tree.column('Max', stretch=0, width=70)
    #for col in self.header:
    # self.tree.heading(col, text=col.title())
    style = ttk.Style()
    style.configure('.', font=('Helvetica', 8), foreground='white')
    style.configure('Treeview', foreground='red')
    style.configure('Treeview.Heading', foreground='green')

    # create scrollbars
    ysb = ttk.Scrollbar(self.tree, orient=tk.VERTICAL, command=self.tree.yview)
    #xsb = ttk.Scrollbar(self.tree, orient=tk.HORIZONTAL, command=self.tree.xview)
    self.tree['yscroll'] = ysb.set
    #self.tree['xscroll'] = xsb.set

    # add tree and scrollbars to frame
    #ysb.pack(side=tk.RIGHT, fill=tk.Y)
    self.tree.pack()

    # set frame resizing priorities
    #frame.rowconfigure(0, weight=1)
    #frame.columnconfigure(0, weight=1)

    self.connect()
    self.get_data()


    def run(self):
    self.master.mainloop()


    def connect(self):
    self.client_socket = socket.socket()
    self.client_socket.settimeout(self.timeout)
    try:
    self.client_socket.connect((self.host, self.port))
    except (socket.timeout, ConnectionRefusedError) as Error:
    print(Error)
    self.stop()
    return
    self.client_socket.settimeout(None)
    # Make a file-like object out of the connection
    self.connection = self.client_socket.makefile('rb')
    self.running = True


    def get_data(self):
    if self.running:
    try:
    calcsize = self.connection.read(struct.calcsize('<L'))
    if not calcsize:
    self.stop()
    self.connect()
    self.get_data()
    return
    data_len = struct.unpack('<L', calcsize)[0]
    except struct.error as Error:
    print(Error)
    self.stop()
    self.connect()
    self.get_data()
    return
    if data_len:
    data = self.connection.read(data_len).decode()
    data = json.loads(data)
    self.populate_root(data)
    data=None
    self.master.after(self.update_interval, self.get_data)


    def populate_root(self, data):
    for node, _dic in data.items():
    #print(node)
    parent = self.tree.insert('', 'end', text=node, values=[node], tags=('node'), open=False)
    if isinstance(_dic, dict):
    self.populate_tree(parent, _dic)


    def populate_tree(self, parent, children):
    # parent - id of node acting as parent
    # children - list of sensors belonging to the 'parent' node
    for k, v in children.items():
    #print("{} => {}".format(k, v))
    for index, type in enumerate(v):
    #print(type)
    if type == "Type":
    self.tree.insert(parent, 'end', text=v["Type"], values=[v["Type"]])
    self.tree.insert(parent, 'end', text=v["Name"], values=[v["Name"], v['Value'], v['Min'], v['Max']])


    def stop(self):
    self.running = False
    try: self.connection.close()
    except: pass
    try: self.client_socket.close()
    except: pass
    self.client_socket = None


    def quit(self):
    self.running = False
    self.master.destroy()
    print('\nQuit\n')


    def main():
    screen_width = 400
    screen_height = 500
    try:
    tkinter_app = GUI(host='192.168.0.10', port=7060, resolution="{0}x{1}".format(screen_width, screen_height))
    tkinter_app.run()
    except (KeyboardInterrupt, SystemExit):
    print('\nQuit\n')
    tkinter_app.quit()
    except Exception as error:
    print('Error: ' + str(error))
    sys.exit()


    if __name__ == '__main__':
    main()


    #EOF
    [/php]

  • Weil sich noch keiner gemeldet hat, ich kann es heute abend mal testen und mir das mit der Scrollbar anschauen. Auch wenn ich über Tkinter eigentlich hinweg bin :)

    Edit: warum der Screenshot jetz von Windows kommt verstehe ich nicht. Soll hier die GUI nicht auf dem Pi laufen? Egal, um auf Windows und macOS wenigstens einen halbwegs nativen Look hinzubekommen könntest du auch die Standardwidgets alle mit ttk zeichnen.

    LG

  • Zitat von &quot;linusg&quot; pid='291877' dateline='1500631142'


    Edit: warum der Screenshot jetz von Windows kommt verstehe ich nicht.

    Weil ich am Pi keinen Monitor angeschlossen hab und das über Xming läuft - das GUI Script führe ich aber auf dem Pi aus ;)

  • Sodele, ich wär dann soweit :shy:

    Ergebnis:

    Normal:

    Scrollbar benötigt und aktiv:

    Größeres Fenster:

    Weil ich mich schon länger von all meinen Windoofs verabschiedet habe, und das mit der VM zu frickelig wäre, habe ich diesen Teil:

    [code=php]
    self.connect()
    self.get_data()
    [/php]

    ersetzt durch

    [code=php]
    for i in range(5):
    parent = self.tree.insert('', 'end', values=['Parent {}'.format(i)], tags='node', open=False)
    for j in range(5):
    self.tree.insert(parent, 'end', values=['Child {}'.format(j), '2', '1', '3'], tags='node', open=False)
    [/php]


    um Dummy-Daten im ähnlichen Format zu erzeugen. Sollte aber auch mit den echten Daten klappen :)

    Der neue Code:

    [code=php]#!/usr/bin/python3

    """
    Creator: meigrafd
    Copyright (C) 2017 by meiraspi@gmail.com published under the Creative Commons License (BY-NC-SA)
    """

    import sys
    import json
    import socket
    import select
    import struct
    import tkinter as tk
    import tkinter.ttk as ttk


    class GUI(object):
    def __init__(self, resolution='640x480', host='127.0.0.1', port=7060, timeout=5, interval=5000):
    self.host = host
    self.port = port
    self.gui_resolution = resolution
    self.timeout = timeout
    self.running = False
    self.update_interval = interval # ms
    self.master = tk.Tk()
    # self.master.geometry(self.gui_resolution)
    self.master.protocol('WM_DELETE_WINDOW', self.quit)
    self.main()

    def main(self):
    # https://stackoverflow.com/q/32051780/2641799
    frame = ttk.Frame(self.master)
    frame.pack(fill=tk.BOTH, expand=1)

    header = ['Sensor', 'Value', 'Min', 'Max']
    self.tree = ttk.Treeview(frame, columns=header, show='headings')

    # setup column headings
    self.tree.heading('#1', text='Sensor', anchor=tk.W)
    self.tree.heading('Value', text='Value', anchor=tk.W)
    self.tree.column('Value', stretch=0, width=70)
    self.tree.heading('Min', text='Min', anchor=tk.W)
    self.tree.column('Min', stretch=0, width=70)
    self.tree.heading('Max', text='Max', anchor=tk.W)
    self.tree.column('Max', stretch=0, width=70)
    # for col in self.header:
    # self.tree.heading(col, text=col.title())
    style = ttk.Style()
    style.configure('.', font=('Helvetica', 8), foreground='white')
    style.configure('Treeview', foreground='red')
    style.configure('Treeview.Heading', foreground='green')

    vsb = ttk.Scrollbar(frame, orient=tk.VERTICAL, command=self.tree.yview)
    self.tree.configure(yscrollcommand=vsb.set)

    self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
    vsb.pack(side=tk.LEFT, fill=tk.Y)

    # set frame resizing priorities
    # frame.rowconfigure(0, weight=1)
    # frame.columnconfigure(0, weight=1)

    self.connect()
    self.get_data()

    def run(self):
    self.master.mainloop()

    def connect(self):
    self.client_socket = socket.socket()
    self.client_socket.settimeout(self.timeout)
    try:
    self.client_socket.connect((self.host, self.port))
    except (socket.timeout, ConnectionRefusedError) as error:
    print(error)
    self.stop()
    else:
    self.client_socket.settimeout(None)
    # Make a file-like object out of the connection
    self.connection = self.client_socket.makefile('rb')
    self.running = True

    def get_data(self):
    if self.running:
    try:
    calcsize = self.connection.read(struct.calcsize('<L'))
    if not calcsize:
    self.stop()
    self.connect()
    self.get_data()
    return
    data_len = struct.unpack('<L', calcsize)[0]
    except struct.error as error:
    print(error)
    self.stop()
    self.connect()
    self.get_data()
    else:
    if data_len:
    data = self.connection.read(data_len).decode()
    data = json.loads(data)
    self.populate_root(data)
    data = None
    self.master.after(self.update_interval, self.get_data)

    def populate_root(self, data):
    for node, _dic in data.items():
    # print(node)
    parent = self.tree.insert('', 'end', text=node, values=[node], tags='node', open=False)
    if isinstance(_dic, dict):
    self.populate_tree(parent, _dic)

    def populate_tree(self, parent, children):
    # parent - id of node acting as parent
    # children - list of sensors belonging to the 'parent' node
    for k, v in children.items():
    # print('{} => {}'.format(k, v))
    for index, type_ in enumerate(v):
    # print(type_)
    if type_ == 'Type':
    self.tree.insert(parent, 'end', text=v['Type'], values=[v['Type']])
    self.tree.insert(parent, 'end', text=v['Name'], values=[v['Name'], v['Value'], v['Min'], v['Max']])

    def stop(self):
    self.running = False
    try: self.connection.close()
    except: pass
    try: self.client_socket.close()
    except: pass
    self.client_socket = None

    def quit(self):
    self.running = False
    self.master.destroy()
    print('\nQuit\n')


    def main():
    screen_width = 400
    screen_height = 500
    try:
    tkinter_app = GUI(host='192.168.0.10', port=7060, resolution='{0}x{1}'.format(screen_width, screen_height))
    tkinter_app.run()
    except (KeyboardInterrupt, SystemExit):
    print('\nQuit\n')
    tkinter_app.quit()
    except Exception as error:
    print('Error: ' + str(error))
    sys.exit()


    if __name__ == '__main__':
    main()[/php]

    Die ganze Magie ist in der Methode main der Klasse GUI:

    [code=php]
    def main(self):
    frame = ttk.Frame(self.master)
    frame.pack(fill=tk.BOTH, expand=1)
    [/php]
    Den Hauptframe mal so konfigurieren, dass er sich in beide Richtungen ausbreitet.


    [code=php]
    vsb = ttk.Scrollbar(frame, orient=tk.VERTICAL, command=self.tree.yview)
    self.tree.configure(yscrollcommand=vsb.set)
    [/php]
    Eine verticale Scrollbar erstellen und dem Tree zuweisen. Wichtig: den frame als parent angeben, nicht den tree! (sonst verhauts das Layout...)


    [code=php]
    self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
    vsb.pack(side=tk.LEFT, fill=tk.Y)
    [/php]
    Den Tree und die Scrollbar beide links ausrichten, vgl. mit CSS float: left; Nachdem der Frame schon den ganzen Platz einnimmt, muss jetzt der Tree den ganzen Platz im Frame einnehmen, abzüglich der Scrollbar. Diese wird vertikal ausgebreitet.


    Ich konnte es nicht lassen,ein paar Sachen stilistisch zu verbessern :daumendreh2:
    (Redundante Klammern, Variablennamen, konsistente Anführungszeichen, Whitespace in leeren Zeilen, PEP8 halt. Kannste ja auch wieder wegmachen :P )

    Hier noch das Diff der Dateinen before.py und after.py. Nur nochmal der Vollständigkeit halber, ich glaub da hat die Forensoftware die Leerzeichen verhauen, taugt also nicht als Patch :denker:

    [code=php]diff --git a/Schreibtisch/before.py b/Schreibtisch/after.py
    index b44c1bf..4daaf2c 100755
    --- a/Schreibtisch/before.py
    +++ b/Schreibtisch/after.py
    @@ -1,8 +1,10 @@
    #!/usr/bin/python3
    -#
    -# Creator: meigrafd
    -# Copyright (C) 2017 by meiraspi@gmail.com published under the Creative Commons License (BY-NC-SA)
    -#
    +
    +"""
    +Creator: meigrafd
    +Copyright (C) 2017 by meiraspi@gmail.com published under the Creative Commons License (BY-NC-SA)
    +"""
    +
    import sys
    import json
    import socket
    @@ -13,27 +15,26 @@ import tkinter.ttk as ttk


    class GUI(object):
    - def __init__(self, resolution="640x480", host='127.0.0.1', port=7060, timeout=5, interval=5000):
    + def __init__(self, resolution='640x480', host='127.0.0.1', port=7060, timeout=5, interval=5000):
    self.host = host
    self.port = port
    self.gui_resolution = resolution
    self.timeout = timeout
    self.running = False
    - self.update_interval = interval #ms
    + self.update_interval = interval # ms
    self.master = tk.Tk()
    - #self.master.geometry(self.gui_resolution)
    - self.master.protocol("WM_DELETE_WINDOW", self.quit)
    + # self.master.geometry(self.gui_resolution)
    + self.master.protocol('WM_DELETE_WINDOW', self.quit)
    self.main()
    -
    -
    - # https://stackoverflow.com/q/32051780/2641799
    +
    def main(self):
    + # https://stackoverflow.com/q/32051780/2641799
    frame = ttk.Frame(self.master)
    - frame.pack()
    -
    + frame.pack(fill=tk.BOTH, expand=1)
    +
    header = ['Sensor', 'Value', 'Min', 'Max']
    self.tree = ttk.Treeview(frame, columns=header, show='headings')
    -
    +
    # setup column headings
    self.tree.heading('#1', text='Sensor', anchor=tk.W)
    self.tree.heading('Value', text='Value', anchor=tk.W)
    @@ -42,50 +43,48 @@ class GUI(object):
    self.tree.column('Min', stretch=0, width=70)
    self.tree.heading('Max', text='Max', anchor=tk.W)
    self.tree.column('Max', stretch=0, width=70)
    - #for col in self.header:
    - # self.tree.heading(col, text=col.title())
    + # for col in self.header:
    + # self.tree.heading(col, text=col.title())
    style = ttk.Style()
    style.configure('.', font=('Helvetica', 8), foreground='white')
    style.configure('Treeview', foreground='red')
    style.configure('Treeview.Heading', foreground='green')
    -
    - # create scrollbars
    - ysb = ttk.Scrollbar(self.tree, orient=tk.VERTICAL, command=self.tree.yview)
    - #xsb = ttk.Scrollbar(self.tree, orient=tk.HORIZONTAL, command=self.tree.xview)
    - self.tree['yscroll'] = ysb.set
    - #self.tree['xscroll'] = xsb.set
    -
    - # add tree and scrollbars to frame
    - #ysb.pack(side=tk.RIGHT, fill=tk.Y)
    - self.tree.pack()
    -
    +
    + vsb = ttk.Scrollbar(frame, orient=tk.VERTICAL, command=self.tree.yview)
    + self.tree.configure(yscrollcommand=vsb.set)
    +
    + self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
    + vsb.pack(side=tk.LEFT, fill=tk.Y)
    +
    # set frame resizing priorities
    - #frame.rowconfigure(0, weight=1)
    - #frame.columnconfigure(0, weight=1)
    + # frame.rowconfigure(0, weight=1)
    + # frame.columnconfigure(0, weight=1)

    self.connect()
    self.get_data()
    -
    -
    +
    def run(self):
    self.master.mainloop()
    -
    -
    +
    def connect(self):
    self.client_socket = socket.socket()
    self.client_socket.settimeout(self.timeout)
    try:
    self.client_socket.connect((self.host, self.port))
    - except (socket.timeout, ConnectionRefusedError) as Error:
    - print(Error)
    + except (socket.timeout, ConnectionRefusedError) as error:
    + print(error)
    self.stop()
    - return
    - self.client_socket.settimeout(None)
    - # Make a file-like object out of the connection
    - self.connection = self.client_socket.makefile('rb')
    - self.running = True
    -
    -
    + else:
    + self.client_socket.settimeout(None)
    + # Make a file-like object out of the connection
    + self.connection = self.client_socket.makefile('rb')
    + self.running = True
    +
    def get_data(self):
    if self.running:
    try:
    @@ -96,40 +95,37 @@ class GUI(object):
    self.get_data()
    return
    data_len = struct.unpack('<L', calcsize)[0]
    - except struct.error as Error:
    - print(Error)
    + except struct.error as error:
    + print(error)
    self.stop()
    self.connect()
    self.get_data()
    - return
    - if data_len:
    - data = self.connection.read(data_len).decode()
    - data = json.loads(data)
    - self.populate_root(data)
    - data=None
    - self.master.after(self.update_interval, self.get_data)
    -
    -
    + else:
    + if data_len:
    + data = self.connection.read(data_len).decode()
    + data = json.loads(data)
    + self.populate_root(data)
    + data = None
    + self.master.after(self.update_interval, self.get_data)
    +
    def populate_root(self, data):
    for node, _dic in data.items():
    - #print(node)
    - parent = self.tree.insert('', 'end', text=node, values=[node], tags=('node'), open=False)
    + # print(node)
    + parent = self.tree.insert('', 'end', text=node, values=[node], tags='node', open=False)
    if isinstance(_dic, dict):
    self.populate_tree(parent, _dic)
    -
    -
    +
    def populate_tree(self, parent, children):
    # parent - id of node acting as parent
    # children - list of sensors belonging to the 'parent' node
    for k, v in children.items():
    - #print("{} => {}".format(k, v))
    - for index, type in enumerate(v):
    - #print(type)
    - if type == "Type":
    - self.tree.insert(parent, 'end', text=v["Type"], values=[v["Type"]])
    - self.tree.insert(parent, 'end', text=v["Name"], values=[v["Name"], v['Value'], v['Min'], v['Max']])
    -
    -
    + # print('{} => {}'.format(k, v))
    + for index, type_ in enumerate(v):
    + # print(type_)
    + if type_ == 'Type':
    + self.tree.insert(parent, 'end', text=v['Type'], values=[v['Type']])
    + self.tree.insert(parent, 'end', text=v['Name'], values=[v['Name'], v['Value'], v['Min'], v['Max']])
    +
    def stop(self):
    self.running = False
    try: self.connection.close()
    @@ -137,8 +133,7 @@ class GUI(object):
    try: self.client_socket.close()
    except: pass
    self.client_socket = None
    -
    -
    +
    def quit(self):
    self.running = False
    self.master.destroy()
    @@ -149,7 +144,7 @@ def main():
    screen_width = 400
    screen_height = 500
    try:
    - tkinter_app = GUI(host='192.168.0.10', port=7060, resolution="{0}x{1}".format(screen_width, screen_height))
    + tkinter_app = GUI(host='192.168.0.10', port=7060, resolution='{0}x{1}'.format(screen_width, screen_height))
    tkinter_app.run()
    except (KeyboardInterrupt, SystemExit):
    print('\nQuit\n')
    @@ -161,6 +156,3 @@ def main():

    if __name__ == '__main__':
    main()
    -
    -
    -#EOF [/php]


    Ich hoffe, das ist etwa so wie du es willst. Wenn du Kritik an meiner Kritik hast, her damit. Nach einer Woche Reise bin ich ganz froh mal wieder was coden zu können und hier zu helfen :thumbs1:

    LG

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!