Problem bei Python-Skript ausführen

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
Sinus444
User
Beiträge: 1
Registriert: Freitag 30. Oktober 2020, 10:38

Hallo Zusammnen,

vorweg: ich komme aus dem Bereich FHEM und habe absolut keine Ahnung von Python. Nun muss ich aber mit einem Python Skript arbeiten und weiss nicht weiter. Vielleicht könnt ihr mir helfen?!

Ich betreibe einen FHEM Server zur Hausautomation. Jetzt habe ich eine Pelletheizung bekommen und habe sie in FHEM eingebunden um deren Daten auslesen zu können. Soweit so gut.
Jedoch sind einige Werte falsch, bzw. unplausibel. Auf Nachfrage bei demjenigen, der das Modul für die Pelletheizung geschrieben hat kam heraus, dass er ein anderes Modell und wahrscheinlich auch eine andere Softwareversion betreibt, als ich.

In dem Thread, in dem wir darüber diskutierten, meldete sich jemand, mit noch einem anderen Modell dieser Firma und sagte, er hat ein Python Skript geschrieben, welches die Werte für meine Heizung anpasst.

Seine Anleitung lautet wie folgt:

1. Daten von der Heizung per SD Karte loggen. Die so erstellte Datei (DAQ00000.DAQ) öffnen und alle Daten zwischen <DAQPRJ> und </DAQPRJ> in eine utf-8 codierte Datei kopieren und das Skript mit dieser Datei laufen lassen.

Das habe ich gemacht. Meine Datendatei habe ich per Editor erstellt und gespeichert. Beide Dateien habe ich in einen Ordner gesteckt und nun weiss ich nicht weiter. Wie lasse ich denn sein Skript mit dieser Datei laufen?

Kann mir da jemand behilflich sein.

Anbei hänge ich die Dateien. Ich sehe gerade, dass ich hier nichts anhängen kann, daher schreibe ich den Inhalt seines Skriptes, als auch meiner Datei hier hin

Vielen dank auch!

Andre

Inhalt des Skripts:

import xml.etree.ElementTree as ET
import sys

def remove_umlaut(string):
"""
Removes umlauts from strings and replaces them with the letter+e convention
:param string: string to remove umlauts from
:return: unumlauted string
"""
u = 'ü'.encode()
U = 'Ü'.encode()
a = 'ä'.encode()
A = 'Ä'.encode()
o = 'ö'.encode()
O = 'Ö'.encode()
ss = 'ß'.encode()

string = string.encode()
string = string.replace(u, b'ue')
string = string.replace(U, b'Ue')
string = string.replace(a, b'ae')
string = string.replace(A, b'Ae')
string = string.replace(o, b'oe')
string = string.replace(O, b'Oe')
string = string.replace(ss, b'ss')

string = string.decode('utf-8')
return string

# channels have to be saved in unicode
if (len(sys.argv)>1):
filename = sys.argv[1]
else:
filename = 'hargassner_channels.xml'

xmldoc=ET.parse(filename)

analogChannels = xmldoc.findall(".//ANALOG/CHANNEL")

for channel in analogChannels:
name = channel.get('name')
name = remove_umlaut(name)
name = name.replace(" ", "_")
id = int(channel.get('id'))
unit = channel.get('unit')

channel_def = 'readingsBulkUpdate($hash, \'{2:03d}_{0}\', $array[{2}].\' {1}\') if( ReadingsVal($name, \'{2:03d}_{0}\', \'\') ne $array[{2}].\' {1}\');'.format(name,unit,id+1)

lastid = id
print(channel_def)

digitalChannels = xmldoc.findall(".//DIGITAL/CHANNEL")

for channel in digitalChannels:
name = channel.get('name')
name = remove_umlaut(name)
name = name.replace(" ", "_")
id = int(channel.get('id'))
bit = int(channel.get('bit'))

channel_def = '''readingsBulkUpdate($hash, \'{0:03d}_{2}\', query_bit($array[{0}], {1})) if( ReadingsVal($name, \'{0:03d}_{2}\', \'\') ne query_bit($array[{0}], {1}));'''.format(lastid+id+2, bit, name)
print(channel_def)



Inhalt meiner Datei:

<ANALOG><CHANNEL id='0' name='ZK' unit=''/><CHANNEL id='1' name='O2' unit='%'/><CHANNEL id='2' name='O2soll' unit='%'/><CHANNEL id='3' name='TK' unit='°C'/><CHANNEL id='4' name='TKsoll' unit='°C'/><CHANNEL id='5' name='TRG' unit='°C'/><CHANNEL id='6' name='SZist' unit='%'/><CHANNEL id='7' name='SZsoll' unit='%'/><CHANNEL id='8' name='Leistung' unit='%'/><CHANNEL id='9' name='ESsoll' unit='%'/><CHANNEL id='10' name='I Es' unit='mA'/><CHANNEL id='11' name='I Ra' unit='mA'/><CHANNEL id='12' name='I Aa' unit='mA'/><CHANNEL id='13' name='I Sr' unit='mA'/><CHANNEL id='14' name='I Rein' unit='mA'/><CHANNEL id='15' name='Taus' unit='°C'/><CHANNEL id='16' name='TA Gem.' unit='°C'/><CHANNEL id='17' name='TPo' unit='°C'/><CHANNEL id='18' name='TPmo' unit='°C'/><CHANNEL id='19' name='TPm' unit='°C'/><CHANNEL id='20' name='TPmu' unit='°C'/><CHANNEL id='21' name='TPu' unit='°C'/><CHANNEL id='22' name='TFW' unit='°C'/><CHANNEL id='23' name='TRL' unit='°C'/><CHANNEL id='24' name='TRLsoll' unit='°C'/><CHANNEL id='25' name='Tplat' unit='°C'/><CHANNEL id='26' name='BRT' unit='°C'/><CHANNEL id='27' name='Regler K' unit=''/><CHANNEL id='28' name='KeBrstScale' unit='%'/><CHANNEL id='29' name='ESRegler' unit='%'/><CHANNEL id='30' name='BLDC_ES ist' unit='rpm'/><CHANNEL id='31' name='BLDC_ES soll' unit='rpm'/><CHANNEL id='32' name='LZ ES seit Füll.' unit='Min'/><CHANNEL id='33' name='LZ ES seit Ent.' unit='Min'/><CHANNEL id='34' name='Anzahl Entasch.' unit=''/><CHANNEL id='35' name='Anzahl SR Beweg.' unit=''/><CHANNEL id='36' name='Heiz P Lambda' unit='W'/><CHANNEL id='37' name='Heiz U Lambda' unit='V'/><CHANNEL id='38' name='Heiz I Lambda' unit='mA'/><CHANNEL id='39' name='Sens U Lambda' unit='mV'/><CHANNEL id='40' name='PuffZustand' unit=''/><CHANNEL id='41' name='Puffer_soll' unit='°C'/><CHANNEL id='42' name='Puff Füllgrad' unit='%'/><CHANNEL id='43' name='max.Leist.P3F.HT' unit='%'/><CHANNEL id='44' name='Spreizung' unit='°C'/><CHANNEL id='45' name='AIN17' unit='V'/><CHANNEL id='46' name='Lagerstand' unit='kg'/><CHANNEL id='47' name='Verbrauchszähler' unit='kg'/><CHANNEL id='48' name='UsePos' unit=''/><CHANNEL id='49' name='Störungs Nr' unit=''/><CHANNEL id='50' name='TVL_A' unit='°C'/><CHANNEL id='51' name='TVLs_A' unit='°C'/><CHANNEL id='52' name='TRA_A' unit='°C'/><CHANNEL id='53' name='TRs_A' unit='°C'/><CHANNEL id='54' name='HKZustand_A' unit=''/><CHANNEL id='55' name='FRA Zustand' unit=''/><CHANNEL id='56' name='TVL_1' unit='°C'/><CHANNEL id='57' name='TVLs_1' unit='°C'/><CHANNEL id='58' name='TRA_1' unit='°C'/><CHANNEL id='59' name='TRs_1' unit='°C'/><CHANNEL id='60' name='HKZustand_1' unit=''/><CHANNEL id='61' name='FR1 Zustand' unit=''/><CHANNEL id='62' name='TVL_2' unit='°C'/><CHANNEL id='63' name='TVLs_2' unit='°C'/><CHANNEL id='64' name='TRA_2' unit='°C'/><CHANNEL id='65' name='TRs_2' unit='°C'/><CHANNEL id='66' name='HKZustand_2' unit=''/><CHANNEL id='67' name='FR2 Zustand' unit=''/><CHANNEL id='68' name='TVL_3' unit='°C'/><CHANNEL id='69' name='TVLs_3' unit='°C'/><CHANNEL id='70' name='TRA_3' unit='°C'/><CHANNEL id='71' name='TRs_3' unit='°C'/><CHANNEL id='72' name='HKZustand_3' unit=''/><CHANNEL id='73' name='FR3 Zustand' unit=''/><CHANNEL id='74' name='TVL_4' unit='°C'/><CHANNEL id='75' name='TVLs_4' unit='°C'/><CHANNEL id='76' name='TRA_4' unit='°C'/><CHANNEL id='77' name='TRs_4' unit='°C'/><CHANNEL id='78' name='HKZustand_4' unit=''/><CHANNEL id='79' name='FR4 Zustand' unit=''/><CHANNEL id='80' name='TVL_5' unit='°C'/><CHANNEL id='81' name='TVLs_5' unit='°C'/><CHANNEL id='82' name='TRA_5' unit='°C'/><CHANNEL id='83' name='TRs_5' unit='°C'/><CHANNEL id='84' name='HKZustand_5' unit=''/><CHANNEL id='85' name='FR5 Zustand' unit=''/><CHANNEL id='86' name='TVL_6' unit='°C'/><CHANNEL id='87' name='TVLs_6' unit='°C'/><CHANNEL id='88' name='TRA_6' unit='°C'/><CHANNEL id='89' name='TRs_6' unit='°C'/><CHANNEL id='90' name='HKZustand_6' unit=''/><CHANNEL id='91' name='FR6 Zustand' unit=''/><CHANNEL id='92' name='TBA' unit='°C'/><CHANNEL id='93' name='TBs_A' unit='°C'/><CHANNEL id='94' name='BoiZustand_A' unit=''/><CHANNEL id='95' name='TB1' unit='°C'/><CHANNEL id='96' name='TBs_1' unit='°C'/><CHANNEL id='97' name='BoiZustand_1' unit=''/><CHANNEL id='98' name='TB2' unit='°C'/><CHANNEL id='99' name='TBs_2' unit='°C'/><CHANNEL id='100' name='BoiZustand_2' unit=''/><CHANNEL id='101' name='TB3' unit='°C'/><CHANNEL id='102' name='TBs_3' unit='°C'/><CHANNEL id='103' name='BoiZustand_3' unit=''/><CHANNEL id='104' name='Ext.HK Soll' unit=''/><CHANNEL id='105' name='Ext.HK Soll_2' unit=''/><CHANNEL id='106' name='Ext.HK Soll_3' unit=''/><CHANNEL id='107' name='Höchste Anf' unit=''/><CHANNEL id='108' name='Anf. HKR0' unit='°C'/><CHANNEL id='109' name='Anf. HKR1' unit='°C'/><CHANNEL id='110' name='Anf. HKR2' unit='°C'/><CHANNEL id='111' name='Anf. HKR3' unit='°C'/><CHANNEL id='112' name='Anf. HKR4' unit='°C'/><CHANNEL id='113' name='Anf. HKR5' unit='°C'/><CHANNEL id='114' name='Anf. HKR6' unit='°C'/><CHANNEL id='115' name='Anf. HKR7' unit='°C'/><CHANNEL id='116' name='Anf. HKR8' unit='°C'/><CHANNEL id='117' name='Anf. HKR9' unit='°C'/><CHANNEL id='118' name='Anf. HKR10' unit='°C'/><CHANNEL id='119' name='Anf. HKR11' unit='°C'/><CHANNEL id='120' name='Anf. HKR12' unit='°C'/><CHANNEL id='121' name='Anf. HKR13' unit='°C'/><CHANNEL id='122' name='Anf. HKR14' unit='°C'/><CHANNEL id='123' name='Anf. HKR15' unit='°C'/><CHANNEL id='124' name='T Spülung' unit='°C'/><CHANNEL id='125' name='DiffReg S1' unit='°C'/><CHANNEL id='126' name='DiffReg S2' unit='°C'/><CHANNEL id='127' name='TVG' unit='°C'/><CHANNEL id='128' name='DiffReg2 S3' unit='°C'/><CHANNEL id='129' name='DiffReg2 S4' unit='°C'/><CHANNEL id='130' name='U Netzteil' unit='mV'/><CHANNEL id='131' name='TBB' unit='°C'/><CHANNEL id='132' name='TBs_B' unit='°C'/><CHANNEL id='133' name='BoiZustand_B' unit=''/><CHANNEL id='134' name='TVL_B' unit='°C'/><CHANNEL id='135' name='TVLs_B' unit='°C'/><CHANNEL id='136' name='TRB' unit='°C'/><CHANNEL id='137' name='TRs_B' unit='°C'/><CHANNEL id='138' name='HKZustand_B' unit=''/><CHANNEL id='139' name='TRA_B' unit='°C'/><CHANNEL id='140' name='FRB Zustand' unit=''/></ANALOG><DIGITAL><CHANNEL id='0' bit='0' name='Stb'/><CHANNEL id='0' bit='1' name='Fuellstand'/><CHANNEL id='0' bit='3' name='Es Rein Endl'/><CHANNEL id='0' bit='4' name='HKPA'/><CHANNEL id='0' bit='5' name='MAA'/><CHANNEL id='0' bit='6' name='MAZ'/><CHANNEL id='0' bit='7' name='HKP1'/><CHANNEL id='0' bit='8' name='M1A'/><CHANNEL id='0' bit='9' name='M1Z'/><CHANNEL id='0' bit='10' name='HKP2'/><CHANNEL id='0' bit='11' name='M2A'/><CHANNEL id='0' bit='12' name='M2Z'/><CHANNEL id='0' bit='13' name='Störung'/><CHANNEL id='1' bit='0' name='L Heiz.'/><CHANNEL id='1' bit='1' name='Z Heiz.'/><CHANNEL id='1' bit='2' name='Z Geb.'/><CHANNEL id='1' bit='3' name='AA Run'/><CHANNEL id='1' bit='4' name='AA Dir'/><CHANNEL id='1' bit='5' name='ES Run'/><CHANNEL id='1' bit='6' name='ES Dir'/><CHANNEL id='1' bit='7' name='AS Saug'/><CHANNEL id='1' bit='8' name='AS RA Run'/><CHANNEL id='1' bit='9' name='AS RA Dir'/><CHANNEL id='1' bit='10' name='Rein En'/><CHANNEL id='1' bit='11' name='Rein Run'/><CHANNEL id='1' bit='12' name='RLm_auf'/><CHANNEL id='1' bit='13' name='RLm_zu'/><CHANNEL id='1' bit='14' name='RL Pumpe'/><CHANNEL id='2' bit='0' name='BPA'/><CHANNEL id='2' bit='1' name='BP1'/><CHANNEL id='2' bit='2' name='BP2'/><CHANNEL id='2' bit='3' name='BP3'/><CHANNEL id='2' bit='4' name='BZPA'/><CHANNEL id='2' bit='5' name='BZP1'/><CHANNEL id='2' bit='6' name='BZP2'/><CHANNEL id='2' bit='7' name='BZP3'/><CHANNEL id='2' bit='8' name='EHKP'/><CHANNEL id='2' bit='9' name='EHKP2'/><CHANNEL id='2' bit='10' name='EHKP3'/><CHANNEL id='2' bit='11' name='EHK Anf'/><CHANNEL id='2' bit='12' name='EHK Anf2'/><CHANNEL id='2' bit='13' name='EHK Anf3'/><CHANNEL id='3' bit='0' name='HKP3'/><CHANNEL id='3' bit='1' name='M3A'/><CHANNEL id='3' bit='2' name='M3Z'/><CHANNEL id='3' bit='3' name='HKP4'/><CHANNEL id='3' bit='4' name='M4A'/><CHANNEL id='3' bit='5' name='M4Z'/><CHANNEL id='3' bit='6' name='HKP5'/><CHANNEL id='3' bit='7' name='M5A'/><CHANNEL id='3' bit='8' name='M5Z'/><CHANNEL id='3' bit='9' name='HKP6'/><CHANNEL id='3' bit='10' name='M6A'/><CHANNEL id='3' bit='11' name='M6Z'/><CHANNEL id='3' bit='13' name='PuffP'/><CHANNEL id='3' bit='14' name='Entasch gesp.'/><CHANNEL id='3' bit='15' name='ATW'/><CHANNEL id='4' bit='0' name='HKPB'/><CHANNEL id='4' bit='1' name='MBA'/><CHANNEL id='4' bit='2' name='MBZ'/><CHANNEL id='4' bit='3' name='BPB'/><CHANNEL id='4' bit='4' name='BZPB'/><CHANNEL id='4' bit='8' name='KASK1 Run'/><CHANNEL id='4' bit='9' name='KASK2 Run'/><CHANNEL id='4' bit='10' name='KASK3 Run'/><CHANNEL id='4' bit='11' name='KASK4 Run'/><CHANNEL id='4' bit='12' name='FW Freig.'/><CHANNEL id='4' bit='13' name='sAS Anf Füll'/><CHANNEL id='4' bit='14' name='HKV'/><CHANNEL id='4' bit='15' name='FLP'/><CHANNEL id='5' bit='5' name='Netztrafo'/><CHANNEL id='5' bit='6' name='Netzrelais'/><CHANNEL id='5' bit='7' name='Lagerraum'/><CHANNEL id='5' bit='8' name='Aschebox'/><CHANNEL id='6' bit='0' name='gFlP'/><CHANNEL id='6' bit='1' name='gFlM auf'/><CHANNEL id='6' bit='2' name='gFlM zu'/><CHANNEL id='6' bit='4' name='Spülung Aktiv'/><CHANNEL id='7' bit='0' name='DReg P1'/><CHANNEL id='7' bit='1' name='DReg P2'/><CHANNEL id='7' bit='2' name='DReg Mi auf'/><CHANNEL id='7' bit='3' name='DReg Mi zu'/><CHANNEL id='7' bit='4' name='Oel Out'/><CHANNEL id='7' bit='5' name='DReg2 P1'/><CHANNEL id='7' bit='6' name='DReg2 P2'/><CHANNEL id='7' bit='7' name='DReg2 Mi auf'/><CHANNEL id='7' bit='8' name='DReg2 Mi zu'/></DIGITAL>

Rckstr
User
Beiträge: 19
Registriert: Freitag 15. Mai 2020, 10:04

Du musst Python3 auf deinen Rechner installiert haben um die Datei ausführen zu können.

dann öffne die Commandozeile (cmd) und navigiere in den Ordner wo deine beiden Dateien liegen.
Die Dateien sollten sollten so aussehen:

Code: Alles auswählen

pythondatei.py <- Python Datei die du bekommen hast (Name vor dem ".py" habe ich mir gerade ausgedacht)
datei.xml <- Datei die du erstellt hast. 
jetzt gebe in der Commandozeile ein:

Code: Alles auswählen

python3 pythondatei.py datei.xml
und drücke Enter. Jetzt sollte das Python Programm durchlaufen und die xml Datei auswerten.

Wenn du die xml Datei "hargassner_channels.xml" nennst, kannst du auch einfach

Code: Alles auswählen

python3 pythondatei.py
schreiben und Enter drücken.

/Rckstr
Benutzeravatar
__blackjack__
User
Beiträge: 13930
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sinus444: Anmerkungen zum Quelltext: Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).

Um Bedingungen bei ``if`` gehören keine unnötigen Klammern.

Man muss nicht jedes Zwischenergebnis an einen Namen binden, insbesondere nicht wenn das immer der gleiche Name ist.

`last_id` ist fehleranfällig, denn das ist undefiniert wenn es keine Analogen Kanäle in den Daten gibt.

Die beiden Schleifen im Hauptprogramm sind nahezu identisch, da sollte man eine Funktion herausziehen mit den Gemeinsamkeiten.

Bei `channel_def` sind die einfachen Anführungsstriche innerhalb der Zeichenkette unnötigerweise ”escaped”.

In der `remove_umlaut()` wird komisches gemacht. Umlaute werden in Bytes konvertiert. Die übergebene Zeichenkette wird in Bytes konvertiert. Dann werden auf dem `bytes`-Objekt die Ersetzungen vorgenommen. Und zum Schluss werden die Bytes wieder in eine Zeichenkette umgewandelt. Dieser Umweg über Bytes macht absolut keinen Sinn. Mit Hilfe der `str.translate()`-Methode geht das ganze auch deutlich kompakter und effizienter.

Zwischenstand (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
import sys
import xml.etree.ElementTree as ET

UMLAUTS_TABLE = {
    ord(character): replacement
    for character, replacement in [
        ("ä", "ae"),
        ("ö", "oe"),
        ("ü", "ue"),
        ("Ä", "Ae"),
        ("Ö", "Oe"),
        ("Ü", "Ue"),
        ("ß", "ss"),
    ]
}

CHANNEL_DEF_TEMPLATE = (
    "readingsBulkUpdate($hash, {id_name_string}, {get_value_code})"
    " if(ReadingsVal($name, {id_name_string}, '') ne {get_value_code});"
)


def remove_umlauts(string):
    """
    Removes umlauts from strings and replaces them with the letter+e convention.

    :param string: string to remove umlauts from
    :return: unumlauted string
    """
    return string.translate(UMLAUTS_TABLE)


def build_analog_get_value_code(channel, channel_id):
    unit = channel.get("unit")
    return f"$array[{channel_id}].' {unit}'"


def build_digital_get_value_code(channel, channel_id):
    bit = int(channel.get("bit"))
    return f"query_bit($array[{channel_id}], {bit})"


def process_channels(
    xml_document, channel_type, id_offset, build_get_value_code
):
    channel_id = 0
    for channel in xml_document.findall(f".//{channel_type}/CHANNEL"):
        name = remove_umlauts(channel.get("name")).replace(" ", "_")
        channel_id = int(channel.get("id")) + id_offset
        print(
            CHANNEL_DEF_TEMPLATE.format(
                id_name_string=f"'{channel_id:03d}_{name}'",
                get_value_code=build_get_value_code(channel, channel_id),
            )
        )
    return channel_id + 1


def main():
    filename = sys.argv[1] if len(sys.argv) > 1 else "hargassner_channels.xml"
    xml_document = ET.parse(filename)
    id_offset = 1
    for channel_type, build_get_value_code in [
        ("ANALOG", build_analog_get_value_code),
        ("DIGITAL", build_digital_get_value_code),
    ]:
        id_offset = process_channels(
            xml_document,
            channel_type,
            id_offset,
            build_get_value_code,
        )


if __name__ == "__main__":
    main()
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
Antworten