SolarManager unter Versionsverwaltung
Erster Stand der Hintergrundprozesse, die auf der Synology unter /volume1/homes/wagner/SolarManager laufen: der Manager selbst, die Sammler je Geraet, die MQTT-Bruecke, der Wecker und - neu hinzugezogen - der AutoAction-Runner, der als Hintergrundprozess hierher gehoert und nicht ins Web-Verzeichnis. Zugangsdaten stehen nicht mehr im Quelltext, sondern in config.ini, die nicht mit eingecheckt wird. Vorlage ist config.ini.example, gelesen wird sie von konfig.py. Betroffen waren solarManager.py (Datenbank und Wattpilot), zeit.py, gatherWaterData.py, wecker.py und skoda_testdaten.py, das sich das Passwort bisher aus dem Quelltext eines anderen Moduls herausgesucht hat. Die Kia-Anbindung ist mit dem Fahrzeug entfallen: kiaTest.py, gatherCarData.py und hyundai_kia_connect_api sind nicht mehr dabei, ebenso gatherInverterData.py, auf das nur noch eine auskommentierte Zeile zeigte. Die mitgelieferten Bibliotheken bleiben im Repository - die NAS hat kein pip, sie muessen neben den Skripten liegen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import hashlib
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
PY2 = (2,) <= sys.version_info < (3,)
|
||||
|
||||
MANIFEST_ROOT = 'manifest'
|
||||
MANIFEST_FILE = 'file'
|
||||
MANIFEST_NAME = 'name'
|
||||
MANIFEST_MD5 = 'md5'
|
||||
|
||||
MANIFEST_FILE_NAME = 'manifest.xml'
|
||||
MANIFEST_MD5_EXT = '.md5'
|
||||
|
||||
manifest_files = ['CHANGELOG', 'smdx.xsd']
|
||||
|
||||
|
||||
def xml_indent(elem, level=0):
|
||||
"""
|
||||
Simple XML pretty print support function
|
||||
"""
|
||||
i = "\n" + level*" "
|
||||
if len(elem):
|
||||
if not elem.text or not elem.text.strip():
|
||||
elem.text = i + " "
|
||||
if not elem.tail or not elem.tail.strip():
|
||||
elem.tail = i
|
||||
for elem in elem:
|
||||
xml_indent(elem, level+1)
|
||||
if not elem.tail or not elem.tail.strip():
|
||||
elem.tail = i
|
||||
else:
|
||||
if level and (not elem.tail or not elem.tail.strip()):
|
||||
elem.tail = i
|
||||
|
||||
|
||||
class ManifestError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class File(object):
|
||||
def __init__(self, name=None, md5=None):
|
||||
self.name = name
|
||||
self.md5 = md5
|
||||
|
||||
|
||||
class Manifest(object):
|
||||
def __init__(self, path='.', filename=None):
|
||||
self.path = path
|
||||
self.files = {}
|
||||
self.filename = filename
|
||||
|
||||
if filename:
|
||||
self.from_xml(filename=filename)
|
||||
|
||||
def create(self):
|
||||
self.scan()
|
||||
filename = os.path.join(self.path, MANIFEST_FILE_NAME)
|
||||
self.to_xml_file(filename=filename)
|
||||
md5 = hashlib.md5(open(filename, 'rb').read()).hexdigest()
|
||||
f = open(filename + MANIFEST_MD5_EXT, 'w')
|
||||
f.write(md5)
|
||||
f.close()
|
||||
|
||||
def md5(self):
|
||||
return hashlib.md5(self.to_xml_bytes()).hexdigest()
|
||||
|
||||
def diff(self, m):
|
||||
diff_str = ''
|
||||
for f, md5 in self.files.items():
|
||||
m_md5 = m.files.get(f)
|
||||
if md5 != m_md5:
|
||||
diff_str += '%s: %s %s\n' % (f, md5, m_md5)
|
||||
|
||||
if len(self.files) != len(m.files):
|
||||
for f, md5 in m.files.items():
|
||||
if self.files.get(f) is None:
|
||||
diff_str += '%s: "None" %s\n' % (f, md5)
|
||||
return diff_str
|
||||
|
||||
def scan(self):
|
||||
try:
|
||||
files = os.listdir(self.path)
|
||||
for f in files:
|
||||
name, ext = os.path.splitext(f)
|
||||
if f in manifest_files or (ext == '.xml' and f.startswith('smdx_')):
|
||||
filename = os.path.join(self.path, f)
|
||||
content = open(filename, 'rb').read()
|
||||
# if content.find(b'\r\n') >= 0:
|
||||
# print('windows file ', self.path)
|
||||
content = content.replace(b'\r\n', b'\n')
|
||||
md5 = hashlib.md5(content).hexdigest()
|
||||
self.files[f] = md5
|
||||
except Exception as e:
|
||||
raise ManifestError('Error scanning directory %s: %s' % (self.path, str(e)))
|
||||
|
||||
def scan_strip(self):
|
||||
try:
|
||||
files = os.listdir(self.path)
|
||||
for f in files:
|
||||
name, ext = os.path.splitext(f)
|
||||
if f in manifest_files or (ext == '.xml' and f.startswith('smdx_')):
|
||||
filename = os.path.join(self.path, f)
|
||||
content = open(filename, 'rb').read()
|
||||
if content.find(b'\r\n') >= 0:
|
||||
content = content.replace(b'\r\n', b'\n')
|
||||
fc = open(filename, 'w')
|
||||
fc.write(content)
|
||||
fc.close()
|
||||
md5 = hashlib.md5(content).hexdigest()
|
||||
self.files[f] = md5
|
||||
except Exception as e:
|
||||
raise ManifestError('Error scanning directory %s: %s' % (self.path, str(e)))
|
||||
|
||||
def to_xml(self, parent=None, filename=None):
|
||||
if parent is not None:
|
||||
e = ET.SubElement(parent, MANIFEST_ROOT)
|
||||
else:
|
||||
e = ET.Element(MANIFEST_ROOT)
|
||||
|
||||
for f in sorted(self.files.keys()):
|
||||
attr = {MANIFEST_NAME: f, MANIFEST_MD5: self.files.get(f)}
|
||||
ET.SubElement(e, MANIFEST_FILE, attrib=attr)
|
||||
|
||||
return e
|
||||
|
||||
def to_xml_bytes(self, pretty_print=True):
|
||||
e = self.to_xml()
|
||||
|
||||
if pretty_print:
|
||||
xml_indent(e)
|
||||
|
||||
return ET.tostring(e)
|
||||
|
||||
def to_xml_file(self, filename=None, pretty_print=True, replace_existing=True):
|
||||
xml = self.to_xml_bytes(pretty_print)
|
||||
|
||||
if filename is not None:
|
||||
if replace_existing is False and os.path.exists(filename):
|
||||
raise ManifestError('File %s already exists' % (filename))
|
||||
f = open(filename, 'wb')
|
||||
f.write(xml)
|
||||
f.close()
|
||||
else:
|
||||
if PY2:
|
||||
print(xml)
|
||||
else:
|
||||
print(xml.decode())
|
||||
|
||||
def from_xml(self, element=None, filename=None):
|
||||
if element is None and filename is not None:
|
||||
element = ET.ElementTree(file=filename).getroot()
|
||||
|
||||
if element is None:
|
||||
raise ManifestError('No xml document element')
|
||||
|
||||
if element.tag != MANIFEST_ROOT:
|
||||
raise ManifestError('Unexpected test suite root element %s' % (element.tag))
|
||||
|
||||
for e in element.findall('*'):
|
||||
if e.tag == MANIFEST_FILE:
|
||||
name = e.attrib.get(MANIFEST_NAME)
|
||||
md5 = e.attrib.get(MANIFEST_MD5)
|
||||
if name and md5:
|
||||
self.files[name] = md5
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
path = os.path.dirname(os.path.realpath(__file__))
|
||||
a = Manifest(path)
|
||||
a.scan()
|
||||
a.create()
|
||||
|
||||
# b = Manifest(filename=os.path.join(path, 'manifest.xml'))
|
||||
|
||||
# print a.diff(b)
|
||||
# print '----------------------------------------------------'
|
||||
# print a.to_xml_str()
|
||||
# print a.md5()
|
||||
Reference in New Issue
Block a user