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>
Problem bei Python-Skript ausführen
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:
jetzt gebe in der Commandozeile ein:
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
schreiben und Enter drücken.
/Rckstr
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.
Code: Alles auswählen
python3 pythondatei.py datei.xml
Wenn du die xml Datei "hargassner_channels.xml" nennst, kannst du auch einfach
Code: Alles auswählen
python3 pythondatei.py
/Rckstr
- __blackjack__
- User
- Beiträge: 13931
- 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):
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
— Scott Bellware