Ankündigung

Einklappen
Keine Ankündigung bisher.

Neues Plugin - Resol VBUS / Cosmo Multi, Solarthermie logging

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    [Codebeispiel] Neues Plugin - Resol VBUS / Cosmo Multi, Solarthermie logging

    Moin,

    leider habe ich kein Plugin für Smarthome.py zu diesem Thema gefunden, jedoch für Wiregate und OpenHAB
    Wiregate https://knx-user-forum.de/forum/suppo...arregler-resol
    ...und auch eine Diskussion zu OpenHAB https://knx-user-forum.de/forum/supp...en/openhab/821


    Daher habe ich ein Plugin "geschrieben", mit dem die Daten meiner Solarthermie Anlage ausgelesen werden.
    Mein Regler der Solarthermie Anlage ist ähnlich zum "Resol Systemregler DeltaSol® E" http://www.resol.de/index/produktdet...d/8/sprache/de nämlich eine "Cosmo Multi" http://www.cosmo-info.de/fileadmin/u...OSMO-Multi.pdf

    Das Skript basiert auf diesem Python2 Skript
    https://github.com/herbstmensch/resol-vbus-python
    Die Daten aus diesem Skript werden mittels "Pickle" in eine temporäre Datei geschrieben, die vom Smarthome-Plugin ausgelesen werden.
    (Nicht schön - läuft jedoch :-)

    Nun die Codeschnipsel, die Ihr gerne in Github übernehmen & optimieren dürft:

    README.md

    Code:
    # Resol
    
    ## Requirements/Description
    Description:
    Connects to read-only RESOL VBUS Data over LAN
    Requirements:
    Edit config.py (not yet done via Smarthome.py config)
    Add Resol specific *.json files with content of VBUS
    Python2 needed for Python-Script to read VBUS Data over LAN, source: https://github.com/herbstmensch/resol-vbus-python
    Writeable directory to save output of async-data (Exchange of Python2 -> Phyton3 Script)
    
    ## Supported Hardware
    I.e. Resol VBUS Data over LAN: http://www.resol.de/index/produktdetail/kategorie/1/id/76/sprache/en
    
    ## Configuration
    ### plugin.conf
    
    
    
    [resol]
        class_name = Resol
        class_path = plugins.resol
        host = localhost  # ip of ebusd
        cycle = 60       # cycle of each item
    #    port = 7053       # port of VBUS
    #    username = 'USERNAME'
    #    password = 'PASSWORD'
    
      
      
    ### items.conf
    Items need parameter "json_variable"-
    
    
    
    [resol]
      [[temperature_solar_outside]]
        type = num
        knx_dpt = 5
        knx_send = 15/0/0
        knx_reply = 15/0/0
        json_variable = "Temperatur Sensor 1"
      [[temperature_heating_returnflow_unmixed]]
        type = num
        knx_dpt = 5
        knx_send = 15/0/1
        knx_reply = 15/0/1
        json_variable = "Temperatur Sensor 7"
     [[temperature_heating_returnflow_mixed]]
        type = num
        knx_dpt = 5
        knx_send = 15/0/2
        knx_reply = 15/0/2
        json_variable = "Temperatur Sensor 8"
    __init__.py
    Code:
    #!/usr/bin/env python3
    #
    #########################################################################
    #  Copyright 2015 KNX-Username : KHome  
    #  Inspired by eBus Plug-in & Git-Hub project by "Herbstmensch"
    #  Includes parts of: https://github.com/herbstmensch/resol-vbus-python
    #########################################################################
    #  Free for non-commercial use
    #########################################################################
    
    import pickle
    import time
    import subprocess
    import sys
    import logging
    import socket
    import threading
    
    logger = logging.getLogger('resol')
    
    class Resol():
        _items = []
    
        def __init__(self, smarthome, host, username=None, password=None, cycle=60):
            self._sh = smarthome
            self._host = host
            self._cycle = int(cycle)
            self._username = username
            self._password = password
            self.refresh_cycle = self._cycle
            #logging.warning("Test Init Phase, starting python2")
            self._var = subprocess.Popen(['python2', '/home/pi/smarthome/plugins/resol/resol_background.py'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) #start data receiving in while-loop and save variales via python pickle to a temp file, uses python2
    
        def run(self):
            logging.warning("run function")
            self.alive = True
            self._sh.scheduler.add('resolcycle', self.refresh, prio=5, cycle=self._cycle, offset=2)
            # if you want to create child threads, do not make them daemon = True!
            # They will not shutdown properly. (It's a python bug)
    #
        def stop(self):
            self.alive = False
    
        def parse_item(self, item):
            if 'json_variable' in item.conf:
                self._items.append(item)
                return self.update_item
                #logger.debug("parse item: {0}".format(item))
    #
    ##skeleton part
    #    def parse_logic(self, logic):
    #        if 'xxx' in logic.conf:
    #            # self.function(logic['name'])
    #            pass
    #
        def update_item(self, item, caller=None, source=None, dest=None):
            #logging.warning("update function")
            if caller != 'Resol':
                #logger.info("update item: {0}".format(item.id()))
                value = str(int(item()))
    
        def refresh(self):
            #logging.warning("refresh function")
            for item in self._items:
                time.sleep(1)
                resol_variable = item.conf['json_variable']
                value = self.request(resol_variable)
                #logging.warning(resol_variable)
                #logging.warning(value)
                #if reading fails (i.e. at broadcast-commands) the value will not be updated
                if value is not None:
                    item(value, 'resol', 'refresh')
                if not self.alive:
                    brea
    
        def request(self, request):
            #logging.warning("request function")
            try:
                fp = open("/tmp/shared.pkl",'rb')
                #logging.warning(request)
                shared = pickle.load(fp)
                answer = shared[request].rsplit(";",2)[0]
                #logging.warning(answer)
                return answer
            except:
                logger.warning("Unexpected error: resol reading shared.pkl")
                #logger.warning("Unexpected error:", sys.exc_info()[0])
    resol_background.py
    Code:
    #!/usr/bin/env python2 
    # -*- coding: utf-8 -*-
    #Talk with Resol VBUS over LAN
    # https://github.com/herbstmensch/resol-vbus-python
    
    import socket
    import time
    import sys
    import json
    import pickle
    import codecs
    
    import sys
    reload(sys)  
    sys.setdefaultencoding('Cp1252')
    
    # Load settings
    try:
        import config
    except:
        sys.exit("config.py not found!")
    
    # Load Message specification
    try:
        import spec
    except:
        sys.exit("Could not load Message Specification")
    
    
    # Logs in onto the DeltaSol BS Plus over LAN. Also starts (and maintains) the
    # actual stream of data.
    def login():
        dat = recv()
    
        #Check if device answered
        if dat != "+HELLO\n":
            return False
    
        #Send Password
        send("PASS %s\n" % config.vbus_pass)
    
        dat = recv()
    
        return dat.startswith("+OK")
    
    
    def load_data():
        #Request Data
        global new_data
        send("DATA\n")
    
        dat = recv()
    
        #Check if device is ready to send Data
        if not dat.startswith("+OK"):
            return
        init_first = 1
        timeout = time.time() + 60*2 
        while len(result) < config.expected_packets and time.time() < timeout:
            if time.time() > timeout:
               break
            else:
               timeout = time.time() + 60*2 
            buf = readstream()
            msgs = splitmsg(buf)
            for msg in msgs:
                if "PV1" == get_protocolversion(msg):
                    if init_first == 1:
                        result2 = {}
                        new_data = parse_payload(msg, True, result2)
                        init_first = init_first+1
                    else:
                        old_data = new_data
                        result2 = {}
                        new_data = parse_payload(msg, False,result2)
                        if isinstance(new_data,dict) and isinstance(old_data,dict) :
                            check_changes(old_data, new_data)
                    if config.debug:
                        print format_message_pv1(msg)
                elif "PV2" == get_protocolversion(msg):
                    if config.debug:
                        print format_message_pv2(msg)
    
    
    # Receive 1024 bytes from stream
    def recv():
        dat = sock.recv(1024)
        return dat
    
    def check_changes(old_data, new_data):
        if cmp(old_data, new_data) == 0:
            a=0
            # they are the same
        else:
            #print "not the same"
            #
            # continoues reading, write to file, uses module pickle
            d= DictDiffer(old_data,new_data)
            changedlist= list(d.changed())
            #shared = unicode(new_data, 'utf-8')
            shared = new_data
            fp = codecs.open("/tmp/shared.pkl","w", 'utf-8')
            #fp = codecs.open("shared.pkl","w")
            pickle.dump(shared, fp)
            fp.close
            #
            #for field in (changedlist):
            #    print field + "; " + new_data[field]
    
          #                   print field['name'] + ": "+ result[get_source_name(msg)][field['name'][0]]
    
    # Sends given bytes over the stram. Adds debug
    def send(dat):
        sock.send(dat)
    
    
    # Read Data until minimum 1 message is received
    def readstream():
        data = recv()
        while data.count(chr(0xAA)) < 4:
            data += recv()
        return data
    
    
    #Split Messages on Sync Byte
    def splitmsg(buf):
        return buf.split(chr(0xAA))[1:-1]
    
    
    # Format 1 byte as String
    def format_byte(byte):
        return hex(ord(byte))[0:2] + '0' + hex(ord(byte))[2:] if len(hex(ord(byte))) < 4 else hex(ord(byte))
    
    
    # Extract protocol Version from msg
    def get_protocolversion(msg):
        if hex(ord(msg[4])) == '0x10': return "PV1"
        if hex(ord(msg[4])) == '0x20': return "PV2"
        if hex(ord(msg[4])) == '0x30': return "PV3"
        return "UNKNOWN"
    
    
    # Extract Destination from msg
    def get_destination(msg):
        return format_byte(msg[1]) + format_byte(msg[0])[2:]
    
    
    #Extract source from msg
    def get_source(msg):
        return format_byte(msg[3]) + format_byte(msg[2])[2:]
    
    
    # Extract command from msg
    def get_command(msg):
        return format_byte(msg[6]) + format_byte(msg[5:6])[2:]
    
    
    # Get count of frames in msg
    def get_frame_count(msg):
        return gb(msg, 7, 8)
    
    
    # Extract payload from msg
    def get_payload(msg):
        payload = ''
        for i in range(get_frame_count(msg)):
            payload += integrate_septett(msg[9+(i*6):15+(i*6)])
        return payload
    
    
    # parse payload and put result in result
    def parse_payload(msg, printall, packetdict):
        payload = get_payload(msg)
        for packet in spec.spec['packet']:
            if packet['source'] == get_source(msg) and packet['destination'] == get_destination(msg) and packet['command'] == get_command(msg):
                #print packet
    
    
                for field in packet['field']:
                    # result[get_source_name(msg)][field['name']] = str(gb(payload, int(field['offset']), int(field['offset'])+((int(field['bitSize'])+1) / 8)) * (float(field['factor']) if field.has_key('factor') else 1)) + field['unit'] if 'unit' in field else ''
                    if field.has_key('offset'):
                         packetdict[field['name']] = str(gb(payload, int(field['offset']), int(field['offset'])+((int(field['bitSize'])+1) / 8)) * (float(field['factor']) if field.has_key('factor') else 1)) + "; " + (field['unit'] if field.has_key('unit') else '')
                         if printall:
                             # initial reading, write to file, uses module pickle
                             #shared = unicode(packetdict, 'utf-8')
                             shared = packetdict
                             fp = codecs.open("/tmp/shared.pkl","w", 'utf-8')
                             #fp = codecs.open("shared.pkl","w")
                             pickle.dump(shared, fp)
                             fp.close
                             #print field['name'] + "; "+ packetdict[field['name']]
    
                return packetdict
    
    def format_message_pv1(msg):
        parsed = "PARSED: \n"
        parsed += "    ZIEL".ljust(15,'.')+": " + get_destination(msg) + "\n"
        parsed += "    QUELLE".ljust(15,'.')+": " + get_source(msg) + " " + get_source_name(msg) + "\n"
        parsed += "    PROTOKOLL".ljust(15,'.')+": " + get_protocolversion(msg) + "\n"
        parsed += "    BEFEHL".ljust(15,'.')+": " + get_command(msg) + "\n"
        parsed += "    ANZ_FRAMES".ljust(15,'.')+": " + str(get_frame_count(msg)) + "\n"
        parsed += "    CHECKSUM".ljust(15,'.')+": " + format_byte(msg[8]) + "\n"
        for i in range(get_frame_count(msg)):
            integrated = integrate_septett(msg[9+(i*6):15+(i*6)])
            parsed += ("    NB"+str(i*4+1)).ljust(15,'.')+": " + format_byte(msg[9+(i*6)]) + " - " + format_byte(integrated[0]) + "\n"
            parsed += ("    NB"+str(i*4+2)).ljust(15,'.')+": " + format_byte(msg[10+(i*6)]) + " - " + format_byte(integrated[1]) + "\n"
            parsed += ("    NB"+str(i*4+3)).ljust(15,'.')+": " + format_byte(msg[11+(i*6)]) + " - " + format_byte(integrated[2]) + "\n"
            parsed += ("    NB"+str(i*4+4)).ljust(15,'.')+": " + format_byte(msg[12+(i*6)]) + " - " + format_byte(integrated[3]) + "\n"
            parsed += ("    SEPTETT"+str(i+1)).ljust(15,'.')+": " + format_byte(msg[13+(i*6)]) + "\n"
            parsed += ("    CHECKSUM"+str(i+1)).ljust(15,'.')+": " + format_byte(msg[14+(i*6)]) + "\n"
        parsed += "    PAYLOAD".ljust(15,'.')+": " + (" ".join(format_byte(b) for b in get_payload(msg)))+"\n"
    
        return parsed
    
    
    def format_message_pv2(msg):
        parsed = "PARSED: \n"
        parsed += "    ZIEL1".ljust(15,'.')+": " + format_byte(msg[0:1]) + "\n"
        parsed += "    ZIEL2".ljust(15,'.')+": " + format_byte(msg[1:2]) + "\n"
        parsed += "    QUELLE1".ljust(15,'.')+": " + format_byte(msg[2:3]) + "\n"
        parsed += "    QUELLE2".ljust(15,'.')+": " + format_byte(msg[3:4]) + "\n"
        parsed += "    PROTOKOLL".ljust(15,'.')+": " + format_byte(msg[4:5]) + "\n"
        parsed += "    BEFEHL1".ljust(15,'.')+": " + format_byte(msg[5:6]) + "\n"
        parsed += "    BEFEHL2".ljust(15,'.')+": " + format_byte(msg[6:7]) + "\n"
        parsed += "    ID1".ljust(15,'.')+": " + format_byte(msg[7:8]) + "\n"
        parsed += "    ID2".ljust(15,'.')+": " + format_byte(msg[8:9]) + "\n"
        parsed += "    WERT1".ljust(15,'.')+": " + format_byte(msg[9:10]) + "\n"
        parsed += "    WERT2".ljust(15,'.')+": " + format_byte(msg[10:11]) + "\n"
        parsed += "    WERT3".ljust(15,'.')+": " + format_byte(msg[11:12]) + "\n"
        parsed += "    WERT4".ljust(15,'.')+": " + format_byte(msg[12:13]) + "\n"
        parsed += "    SEPTETT".ljust(15,'.')+": " + format_byte(msg[13:14]) + "\n"
        parsed += "    CHECKSUM".ljust(15,'.')+": " + format_byte(msg[14:15]) + "\n"
    
        return parsed
    
    
    def get_compare_length(mask):
        i = 1
        while i < 6 and mask[i] != '0':
            i += 1
        return i+1
    
    
    def get_source_name(msg):
        src = format_byte(msg[3]) + format_byte(msg[2])[2:]
        for device in spec.spec['device']:
            if src[:get_compare_length(device['mask'])] == device['address'][:get_compare_length(device['mask'])]:
                return device['name'] if get_compare_length(device['mask']) == 7 else str(device['name']).replace('#',device['address'][get_compare_length(device['mask'])-1:],1)
        return ""
    
    
    def integrate_septett(frame):
        data = ''
        septet = ord(frame[4])
    
        for j in range(4):
            if septet & (1 /< /< j):
                data += chr(ord(frame[j]) | 0x80)
            else:
                data += frame[j]
    
        return data
    
    class DictDiffer(object):
        """
        Calculate the difference between two dictionaries as:
        (1) items added
        (2) items removed
        (3) keys same in both but changed values
        (4) keys same in both and unchanged values
        """
        def __init__(self, current_dict, past_dict):
            self.current_dict, self.past_dict = current_dict, past_dict
            self.current_keys, self.past_keys = [
                set(d.keys()) for d in (current_dict, past_dict)
            ]
            self.intersect = self.current_keys.intersection(self.past_keys)
    
        def added(self):
            return self.current_keys - self.intersect
    
        def removed(self):
            return self.past_keys - self.intersect
    
        def changed(self):
            return set(o for o in self.intersect
                       if self.past_dict[o] != self.current_dict[o])
    
        def unchanged(self):
            return set(o for o in self.intersect
                       if self.past_dict[o] == self.current_dict[o])
    
        
    # Gets the numerical value of a set of bytes (respect Two's complement by value Range)
    def gb(data, begin, end):  # GetBytes
        wbg = sum([0xff /< /< (i * 8) for i, b in enumerate(data[begin:end])])
        s = sum([ord(b) /< /< (i * 8) for i, b in enumerate(data[begin:end])])
        
        
        if s >= wbg/2:
            s = -1 * (wbg - s)
        return s
        
    
    if __name__ == '__main__':
        
        while 1:
        
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
            sock.connect(config.address)
    
            result = dict()
    
            login()
    
            load_data()
    
        #   print json.dumps(result)
    
            try:
                sock.shutdown(0)
            except:
                pass
            sock.close()
            sock = None
            
            time.sleep(3)
    config.py --> IP und Passwort editieren
    Code:
    address = ("192.168.178.x", 7053)
    vbus_pass = "PASSWORD"
    spec_file = "/home/pi/smarthome/plugins/resol/VBusSpecificationCosmoMulti2012.json"
    debug = False
    expected_packets = 2
    spec.py (unverändert)
    Code:
    #!/usr/bin/env python2
    
    __author__ = 'Tim'
    import json
    import sys
    import config
    
    # Load given specFile. Specfile was created from original
    # RESOL Configuration File XML shippes with RSC (Resol Service Center)
    # using XML to JSON converter at http://www.utilities-online.info/xmltojson
    with open(config.spec_file) as json_data:
        data = json.load(json_data)
        try:
            spec = data['vbusSpecification']
        except:
            sys.exit('Cannot load Spec')
    
    if config.debug:
        for device in spec['device']:
            print device
    
        for packet in spec['packet']:
            print packet
            for field in packet['field']:
                print "  " + str(field)
    
    json_data.close()
    VBusSpecificationCosmoMulti2012.json
    Code:
    {
      "vbusSpecification": {
        "device": [
          {
            "address": "0x7821",
            "mask": "0xFFFF",
            "name": "COSMO Multi",
            "isMaster": "true"
          },
          {
            "address": "0x7822",
            "mask": "0xFFFF",
            "name": "COSMO Multi WMZ",
            "isMaster": "false"
          },
          {
            "address": "0x7831",
            "mask": "0xFFFF",
            "name": "COSMO Multi HK 1 Estrichtrockung Modul 1",
            "isMaster": "false"
          },
          {
            "address": "0x7832",
            "mask": "0xFFFF",
            "name": "COSMO Multi HK 2 Estrichtrockung Modul 2",
            "isMaster": "false"
          },
          {
            "address": "0x7833",
            "mask": "0xFFFF",
            "name": "COSMO Multi HK 3 Estrichtrockung Modul 3",
            "isMaster": "false"
          },
          {
            "address": "0x7834",
            "mask": "0xFFFF",
            "name": "COSMO Multi HK Estrichtrockung Lokal",
            "isMaster": "false"
          }
        ],
        "packet": [
          {
            "destination": "0x0010",
            "source": "0x7821",
            "command": "0x0100",
            "field": [
              {
                "-commonUsage": "collector1",
                "offset": "0",
                "name": "Temperatur Sensor 1",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "-commonUsage": "store1",
                "offset": "2",
                "name": "Temperatur Sensor 2",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "4",
                "name": "Temperatur Sensor 3",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "6",
                "name": "Temperatur Sensor 4",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "8",
                "name": "Temperatur Sensor 5",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "10",
                "name": "Temperatur Sensor 6",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "12",
                "name": "Temperatur Sensor 7",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "14",
                "name": "Temperatur Sensor 8",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "16",
                "name": "Temperatur Sensor 9",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "18",
                "name": "Temperatur Sensor 10",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "20",
                "name": "Einstrahlung CS",
                "bitSize": "15",
                "factor": "1",
                "unit": " W/m²"
              },
              {
                "offset": "22",
                "name": "Impulse 1 V40",
                "bitSize": "16",
                "factor": "1",
                "unit": " "
              },
              {
                "offset": "24",
                "name": "Digital Input",
                "bitSize": "16",
                "factor": "1",
                "unit": " "
              },
              {
                "offset": "26",
                "name": "Drehzahl Relais 1",
                "bitSize": "7",
                "unit": " %"
              },
              {
                "offset": "27",
                "name": "Drehzahl Relais 2",
                "bitSize": "7",
                "unit": " %"
              },
              {
                "offset": "28",
                "name": "Drehzahl Relais 3",
                "bitSize": "7",
                "unit": " %"
              },
              {
                "offset": "29",
                "name": "Drehzahl Relais 4",
                "bitSize": "7",
                "unit": " %"
              },
              {
                "offset": "30",
                "name": "Drehzahl Relais 5",
                "bitSize": "7",
                "unit": " %"
              },
              {
                "offset": "31",
                "name": "Drehzahl Relais 6",
                "bitSize": "7",
                "unit": " %"
              },
              {
                "offset": "32",
                "name": "Drehzahl Relais 7",
                "bitSize": "7",
                "unit": " %"
              },
              {
                "-commonUsage": "error",
                "offset": "36",
                "name": "Fehlermaske",
                "bitSize": "16"
              },
              {
                "offset": "38",
                "name": "Meldungen",
                "bitSize": "16"
              },
              {
                "offset": "40",
                "name": "System",
                "bitSize": "7"
              },
              {
                "offset": "42",
                "name": "Schema",
                "bitSize": "16"
              },
              {
                "offset": "44",
                "name": "Vorlauf Soll HK1 Modul Sensor 18",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "46",
                "name": "Status HK1 Modul",
                "bitSize": "16"
              },
              {
                "offset": "48",
                "name": "Vorlauf Soll HK2 Modul Sensor 25",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "50",
                "name": "Status HK2 Modul",
                "bitSize": "16"
              },
              {
                "offset": "52",
                "name": "Vorlauf Soll HK3 Modul Sensor 32",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "54",
                "name": "Status HK3 Modul",
                "bitSize": "16"
              },
              {
                "offset": "56",
                "name": "Vorlauf Soll Heizkreis Sensor 11",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "58",
                "name": "Status Heizkreis",
                "bitSize": "16"
              },
              {
                "offset": "62",
                "name": "Systemzeit",
                "bitSize": "15",
                "format": "t",
                "timeRef": "1"
              },
              {
                "offset": "64",
                "name": "Jahr",
                "bitSize": "15",
                "factor": "1"
              },
              {
                "offset": "66",
                "name": "Monat",
                "bitSize": "7",
                "factor": "1"
              },
              {
                "offset": "67",
                "name": "Tag",
                "bitSize": "7",
                "factor": "1"
              },
              {
                "name": "Version",
                "field": [
                  {
                    "offset": "60",
                    "bitSize": "7",
                    "factor": "1"
                  },
                  {
                    "offset": "61",
                    "bitSize": "7",
                    "factor": "0,01"
                  }
                ],
                "format": "F2"
              }
            ]
          },
          {
            "destination": "0x0010",
            "source": "0x7822",
            "command": "0x0100",
            "field": [
              {
                "offset": "0",
                "name": "Temperatur Vorlauf",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "2",
                "name": "Temperatur Rücklauf",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "4",
                "name": "Durchfluss Sensor 8",
                "bitSize": "15",
                "unit": " l/h"
              },
              {
                "-commonUsage": "heat",
                "name": "Wärmemenge",
                "unit": " Wh",
                "field": [
                  {
                    "offset": "6",
                    "bitSize": "16",
                    "factor": "1"
                  },
                  {
                    "offset": "8",
                    "bitSize": "16",
                    "factor": "1000"
                  },
                  {
                    "offset": "10",
                    "bitSize": "16",
                    "factor": "1000000"
                  }
                ]
              }
            ]
          },
          {
            "destination": "0x0010",
            "source": "0x7831",
            "sourceMask": "0xFFF0",
            "command": "0x0100",
            "field": [
              {
                "offset": "0",
                "name": "Jahr",
                "bitSize": "15",
                "factor": "1"
              },
              {
                "offset": "2",
                "name": "Monat",
                "bitSize": "7",
                "factor": "1"
              },
              {
                "offset": "3",
                "name": "Tag",
                "bitSize": "7",
                "factor": "1"
              },
              {
                "offset": "4",
                "name": "Systemzeit",
                "bitSize": "15",
                "format": "t",
                "timeRef": "1"
              },
              {
                "offset": "6",
                "name": "Status",
                "bitSize": "7"
              },
              {
                "offset": "7",
                "name": "Fehlermeldung",
                "bitSize": "7"
              },
              {
                "offset": "8",
                "name": "Vorlauf-Soll-Temperatur",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "10",
                "name": "Vorlauftemperatur",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "12",
                "name": "Relais Pumpe",
                "bitSize": "7",
                "unit": " %"
              },
              {
                "offset": "13",
                "name": "Relais Mischer Auf",
                "bitSize": "7",
                "unit": " %"
              },
              {
                "offset": "14",
                "name": "Relais Mischer Zu",
                "bitSize": "7",
                "unit": " %"
              },
              {
                "offset": "15",
                "name": "Handebetrieb Relais Pumpe",
                "bitSize": "7"
              },
              {
                "offset": "16",
                "name": "Handebetrieb Relais Mischer Auf",
                "bitSize": "7"
              },
              {
                "offset": "17",
                "name": "Handebetrieb Relais Mischer Zu",
                "bitSize": "7"
              },
              {
                "offset": "18",
                "name": "NH-Anforderung",
                "bitSize": "7"
              },
              {
                "offset": "19",
                "name": "Parameter Start",
                "bitSize": "7"
              },
              {
                "offset": "20",
                "name": "Parameter TStart",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "22",
                "name": "Parameter TMax",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "24",
                "name": "Parameter Anstieg",
                "bitSize": "15",
                "factor": "0.1",
                "unit": " °C"
              },
              {
                "offset": "26",
                "name": "Parameter Anstiegszeit",
                "bitSize": "7",
                "unit": " h"
              },
              {
                "offset": "27",
                "name": "Parameter Haltezeit",
                "bitSize": "7",
                "unit": " d"
              }
            ]
          }
        ]
      }
    }
    Zuletzt geändert von KHome; 28.02.2016, 10:01.

    #2
    Im Code: resol_background.py
    Ist die Zeichenkette /< /< durch Zeichen ohne / zu ersetzen. Es scheint nicht möglich zu sein, zwei Mal das Kleiner-Zeichen zu posten

    und hier das Ganze als Anhang:
    Angehängte Dateien
    Zuletzt geändert von KHome; 28.02.2016, 09:51.

    Kommentar


      #3
      Hallo,
      verstehe ich das richtig, dass Plugin die Daten via LAN empfängt? Ein direkter Anschluss an ein Seriellwandler wie bei :https://knx-user-forum.de/forum/supp...er-resol/page5 ist nicht möglich?

      Hintergrund: Mein Plugin funktioniert nicht mehr auf dem Wiregate und suche nun ersatz-z.B. über das Smarthome.py

      Danke und Gruß,
      Lio

      Kommentar


        #4
        Hi Lio,

        > Daten via LAN <
        Ja

        > Direkter Anschluss via Seriellwandler <
        Nein, ...vielleicht mit Anpassungen

        Welche Hardware verwendest Du, um die VBUS Daten zu empfangen?
        Die o.g. Lösung basiert auf dem Phython-Skript: https://github.com/herbstmensch/resol-vbus-python
        Hier wird ein "Stream" ausgewertet, der via "Socket" = LAN empfangen wird.

        Eine Auswertung der seriellen Schnittstelle ist bei diesem Skript nicht direkt vorgesehen.
        Mit etwas Programmieraufwand könntest Du es ggf. "umbauen"...

        Kommentar


          #5
          Hallo,

          ich versuche das VBUS Plugin ans Laufen zu bringen, scheitere aber am python2 script. Wenn Debug = true gestellt ist, dann bricht das Script schon beim Laden der Standardspec ab. Das habe ich nun auskommentiert, nun hängt er aber in der Login Function von resol.py, er erwartet ja die Antwort "Hello", erhalte aber:

          HTML-Code:
          <?xml version="1.0"?>
          <root xmlns="urn:schemas-upnp-org:device-1-0">
          <specVersion>
          <major>1</major>
          <minor>0</minor>
          </specVersion>
          <device>
          <deviceType>urn:schemas-upnp-org:device:VBus/LAN:1</deviceType>
          <friendlyName>VBus (192.168.2.101)</friendlyName>
          <manufacturer>RESOL GmbH</manufacturer>
          <manufacturerURL>http://www.resol.com</manufacturerURL>
          <modelDescription>VBus/LAN Module</modelDescription>
          <modelName>VBus/LAN</modelName>
          <modelNumber>VBus/LAN</modelNumber>
          <UDN>uuid:upnp_VBus/LAN-001e664005ac</UDN>
          <serviceList>
          <service>
          <serviceType>(null)</serviceType>
          <serviceId>(null)</serviceId>
          <controlURL>(null)</controlURL>
          <eventSubURL>(null)</eventSubURL>
          <SCPDURL>(null)</SCPDURL>
          </service>
          </serviceList>
          <presentationURL>http://192.168.2.101:80</presentationURL>
          </device>
          </root>

          Kommentar


            #6
            Hallo Marcov,

            auf der GITHUB Seite wird folgendes beschrieben:
            If anything wents wrong, you can enable debug flag in config.py. This will print some basic information while executing the script, but will destroy the JSON output.
            Ich empfehle Dir erstmal mit diesem Skript und Python2 auf der Konsole zu starten:
            https://github.com/herbstmensch/resol-vbus-python
            Wenn das erstmal läuft, dann klappt es bestimmt auch mit dem oben modifizierten Skript

            Kommentar


              #7
              Hi, Danke für die Rückmeldung - mein erste Fehler war, dass ich den Port auf den im Webinterface ungestellt habe, deshalb konnte ich mich nicht einloggen. Es muss also immer Port 7053 sein, egal was man im Webinterface des VBUS/Lan einstellt.
              Ich habe mich nun noch einmal damit befasst. Die parse_payload Funktion bricht bei mir mit folgendem Fehler ab:
              PHP-Code:
              Traceback (most recent call last):
                
              File "resol_background.py"line 325in <module>
                  
              load_data()
                
              File "resol_background.py"line 75in load_data
                  new_data 
              parse_payload(msgTrueresult2)
                
              File "resol_background.py"line 182in parse_payload
                  
              if packet['source'] == get_source(msg) and packet['destination'] == get_destination(msg) and packet['command'] == get_command(msg):
              TypeErrorstring indices must be integers 
              nehme ich die mitgelieferte CosmoMulti.json datei erhalte ich diesen Fehler nicht, die Datei wird aber leider trotzdem nicht geschrieben.

              hier auch meine .json Datei, ggf. habe ich hier einen Fehler?

              PHP-Code:
              {
                
              "vbusSpecification": {
                  
              "device": {
                    
              "address""0x4221",
                    
              "mask""0xFFFF",
                    
              "name""DeltaSol BS Plus",
                    
              "isMaster""true"
                  
              },
                  
              "packet": {
                    
              "destination""0x0010",
                    
              "source""0x4221",
                    
              "command""0x0100",
                    
              "field": [
                      {
                        
              "-commonUsage""collector1",
                        
              "offset""0",
                        
              "name": [
                          
              "Temperatur Sensor 1",
                          {
                            
              "-lang""en",
                            
              "#text""Temperature sensor 1"
                          
              }
                        ],
                        
              "bitSize""15",
                        
              "factor""0.1",
                        
              "unit"" °F"
                      
              },
                      {
                        
              "-commonUsage""store1",
                        
              "offset""2",
                        
              "name": [
                          
              "Temperatur Sensor 2",
                          {
                            
              "-lang""en",
                            
              "#text""Temperature sensor 2"
                          
              }
                        ],
                        
              "bitSize""15",
                        
              "factor""0.1",
                        
              "unit"" °F"
                      
              },
                      {
                        
              "offset""4",
                        
              "name": [
                          
              "Temperatur Sensor 3",
                          {
                            
              "-lang""en",
                            
              "#text""Temperature sensor 3"
                          
              }
                        ],
                        
              "bitSize""15",
                        
              "factor""0.1",
                        
              "unit"" °F"
                      
              },
                      {
                        
              "offset""6",
                        
              "name": [
                          
              "Temperatur Sensor 4",
                          {
                            
              "-lang""en",
                            
              "#text""Temperature sensor 4"
                          
              }
                        ],
                        
              "bitSize""15",
                        
              "factor""0.1",
                        
              "unit"" °F"
                      
              },
                      {
                        
              "offset""8",
                        
              "name": [
                          
              "Drehzahl Pumpe 1",
                          {
                            
              "-lang""en",
                            
              "#text""Pump speed 1"
                          
              }
                        ],
                        
              "bitSize""7",
                        
              "unit"" %"
                      
              },
                      {
                        
              "offset""9",
                        
              "name": [
                          
              "Drehzahl Pumpe 2",
                          {
                            
              "-lang""en",
                            
              "#text""Pump speed 2"
                          
              }
                        ],
                        
              "bitSize""7",
                        
              "unit"" %"
                      
              },
                      {
                        
              "offset""10",
                        
              "name": [
                          
              "Relaismaske",
                          {
                            
              "-lang""en",
                            
              "#text""Relais mask"
                          
              }
                        ],
                        
              "bitSize""8"
                      
              },
                      {
                        
              "-commonUsage""error",
                        
              "offset""11",
                        
              "name": [
                          
              "Fehlermaske",
                          {
                            
              "-lang""en",
                            
              "#text""Error mask"
                          
              }
                        ],
                        
              "bitSize""8"
                      
              },
                      {
                        
              "offset""12",
                        
              "name": [
                          
              "Systemzeit",
                          {
                            
              "-lang""en",
                            
              "#text""System time"
                          
              }
                        ],
                        
              "bitSize""16",
                        
              "format""t",
                        
              "timeRef""1"
                      
              },
                      {
                        
              "offset""14",
                        
              "name": [
                          
              "Schema",
                          {
                            
              "-lang""en",
                            
              "#text""System"
                          
              }
                        ],
                        
              "bitSize""8",
                        
              "factor""1"
                      
              },
                      {
                        
              "offset""15",
                        
              "name""Option Kollektor Max.",
                        
              "bitSize""1",
                        
              "bitPos""0"
                      
              },
                      {
                        
              "offset""15",
                        
              "name""Option Kollektor Min.",
                        
              "bitSize""1",
                        
              "bitPos""1"
                      
              },
                      {
                        
              "offset""15",
                        
              "name""Option Kollektor Frost",
                        
              "bitSize""1",
                        
              "bitPos""2"
                      
              },
                      {
                        
              "offset""15",
                        
              "name""Option Röhrenkollektor",
                        
              "bitSize""1",
                        
              "bitPos""3"
                      
              },
                      {
                        
              "offset""15",
                        
              "name""Option Rückkühlung",
                        
              "bitSize""1",
                        
              "bitPos""4"
                      
              },
                      {
                        
              "offset""15",
                        
              "name""Option WMZ",
                        
              "bitSize""1",
                        
              "bitPos""5"
                      
              },
                      {
                        
              "offset""16",
                        
              "name": [
                          
              "Betriebsstunden Relais 1",
                          {
                            
              "-lang""en",
                            
              "#text""Operating hours relais 1"
                          
              }
                        ],
                        
              "bitSize""16",
                        
              "factor""1"
                      
              },
                      {
                        
              "offset""18",
                        
              "name": [
                          
              "Betriebsstunden Relais 2",
                          {
                            
              "-lang""en",
                            
              "#text""Operating hours relais 2"
                          
              }
                        ],
                        
              "bitSize""16",
                        
              "factor""1"
                      
              },
                      {
                        
              "-commonUsage""heat",
                        
              "name": [
                          
              "Wärmemenge",
                          {
                            
              "-lang""en",
                            
              "#text""Heat amount"
                          
              }
                        ],
                        
              "unit"" Btu",
                        
              "field": [
                          {
                            
              "offset""20",
                            
              "bitSize""16",
                            
              "factor""1"
                          
              },
                          {
                            
              "offset""22",
                            
              "bitSize""16",
                            
              "factor""1000"
                          
              },
                          {
                            
              "offset""24",
                            
              "bitSize""16",
                            
              "factor""1000000"
                          
              }
                        ]
                      },
                      {
                        
              "offset""26",
                        
              "name": [
                          
              "Version",
                          {
                            
              "-lang""en",
                            
              "#text""Version"
                          
              }
                        ],
                        
              "bitSize""16",
                        
              "factor""0.01"
                      
              }
                    ]
                  }
                }

              Kommentar


                #8
                Hi,

                bitte lass Dir folgende Variablen vor der If-Abfrage ausgeben, um den Fehler einzugrenzen.
                D.h. vor Zeile 182 einfügen (via
                Code:
                 print( ... )
                oder
                Code:
                logger.warning( ...)
                oder via einer Python IDE
                Code:
                msg
                Code:
                packet['source']
                Code:
                packet['destination']
                Code:
                packet['command']
                Grüße,
                KHome

                Kommentar


                  #9
                  Hi,
                  nach der for-Schleife geht es nicht ->
                  PHP-Code:
                  Traceback (most recent call last):
                    
                  File "resol_background.py"line 329in <module>
                      
                  load_data()
                    
                  File "resol_background.py"line 75in load_data
                      new_data 
                  parse_payload(msgTrueresult2)
                    
                  File "resol_background.py"line 183in parse_payload
                      
                  print "Source: " str(packet['source'] )
                  TypeErrorstring indices must be integers 
                  deshalb habe ich es davor mit:
                  PHP-Code:
                      print "source: " str(spec.spec['packet']['source'])
                      print 
                  "destination: " str(spec.spec['packet']['destination'])
                      print 
                  "command: " str(spec.spec['packet']['command']) 
                  probiert

                  die Ausgabe (entspricht meinem json file):
                  PHP-Code:
                  source0x4221
                  destination
                  0x0010
                  command
                  0x0100 
                  ggf. liegt es daran, dass in der CosmoMulti mehrere Devices und mehrere Pakete enthalten sind, in meinem File aber nur ein Device und Paket?


                  PHP-Code:
                  print "paket: " str(spec.spec['packet']) 
                  ergibt:

                  PHP-Code:
                  paket: {u'source'u'0x4221'u'destination'u'0x0010'u'command'u'0x0100'u'field': [{u'name': [u'Temperatur Sensor 1', {u'-lang'u'en'u'#text'u'Temperature sensor 1'}], u'bitSize'u'15'u'factor'u'0.1'u'-commonUsage'u'collector1'u'offset'u'0'u'unit'u' \xb0F'}, {u'name': [u'Temperatur Sensor 2', {u'-lang'u'en'u'#text'u'Temperature sensor 2'}], u'bitSize'u'15'u'factor'u'0.1'u'-commonUsage'u'store1'u'offset'u'2'u'unit'u' \xb0F'}, {u'bitSize'u'15'u'factor'u'0.1'u'name': [u'Temperatur Sensor 3', {u'-lang'u'en'u'#text'u'Temperature sensor 3'}], u'unit'u' \xb0F'u'offset'u'4'}, {u'bitSize'u'15'u'factor'u'0.1'u'name': [u'Temperatur Sensor 4', {u'-lang'u'en'u'#text'u'Temperature sensor 4'}], u'unit'u' \xb0F'u'offset'u'6'}, {u'bitSize'u'7'u'name': [u'Drehzahl Pumpe 1', {u'-lang'u'en'u'#text'u'Pump speed 1'}], u'unit'u' %'u'offset'u'8'}, {u'bitSize'u'7'u'name': [u'Drehzahl Pumpe 2', {u'-lang'u'en'u'#text'u'Pump speed 2'}], u'unit'u' %'u'offset'u'9'}, {u'bitSize'u'8'u'name': [u'Relaismaske', {u'-lang'u'en'u'#text'u'Relais mask'}], u'offset'u'10'}, {u'bitSize'u'8'u'offset'u'11'u'name': [u'Fehlermaske', {u'-lang'u'en'u'#text'u'Error mask'}], u'-commonUsage'u'error'}, {u'bitSize'u'16'u'format'u't'u'timeRef'u'1'u'name': [u'Systemzeit', {u'-lang'u'en'u'#text'u'System time'}], u'offset'u'12'}, {u'bitSize'u'8'u'factor'u'1'u'name': [u'Schema', {u'-lang'u'en'u'#text'u'System'}], u'offset'u'14'}, {u'bitSize'u'1'u'bitPos'u'0'u'name'u'Option Kollektor Max.'u'offset'u'15'}, {u'bitSize'u'1'u'bitPos'u'1'u'name'u'Option Kollektor Min.'u'offset'u'15'}, {u'bitSize'u'1'u'bitPos'u'2'u'name'u'Option Kollektor Frost'u'offset'u'15'}, {u'bitSize'u'1'u'bitPos'u'3'u'name'u'Option R\xf6hrenkollektor'u'offset'u'15'}, {u'bitSize'u'1'u'bitPos'u'4'u'name'u'Option R\xfcckk\xfchlung'u'offset'u'15'}, {u'bitSize'u'1'u'bitPos'u'5'u'name'u'Option WMZ'u'offset'u'15'}, {u'bitSize'u'16'u'factor'u'1'u'name': [u'Betriebsstunden Relais 1', {u'-lang'u'en'u'#text'u'Operating hours relais 1'}], u'offset'u'16'}, {u'bitSize'u'16'u'factor'u'1'u'name': [u'Betriebsstunden Relais 2', {u'-lang'u'en'u'#text'u'Operating hours relais 2'}], u'offset'u'18'}, {u'field': [{u'bitSize'u'16'u'factor'u'1'u'offset'u'20'}, {u'bitSize'u'16'u'factor'u'1000'u'offset'u'22'}, {u'bitSize'u'16'u'factor'u'1000000'u'offset'u'24'}], u'name': [u'W\xe4rmemenge', {u'-lang'u'en'u'#text'u'Heat amount'}], u'unit'u' Btu'u'-commonUsage'u'heat'}, {u'bitSize'u'16'u'factor'u'0.01'u'name': [u'Version', {u'-lang'u'en'u'#text'u'Version'}], u'offset'u'26'}]} 
                  danke
                  Zuletzt geändert von Marcov; 01.05.2017, 19:53.

                  Kommentar


                    #10
                    Ich habe es nun etwas angepasst, er schreibt aber anscheined noch nicht das Richtige in die shared.pkl. Das Problem besteht darin, dass es nur ein Device und nur ein Paket gibt. Er dann Probleme hat das Dictionary zu lesen,weil er es als List erkennt. Ich habe es nun so geändert:

                    PHP-Code:
                    def parse_payload(msgprintallpacketdict):
                        
                    payload get_payload(msg)
                        
                    packet spec.spec['packet']
                        
                    #for packet in spec.spec:
                        
                    print "Source: " str(packet['source'])
                        print 
                    "destination: " packet['destination']
                        print 
                    "command: " packet['command']
                        if 
                    packet['source'] == get_source(msg) and packet['destination'] == get_destination(msg) and packet['command'] == get_command(msg):
                            
                    #print "FIELD: " + str(packet['field'])


                            #field = packet['field']
                            
                    for field in packet['field']:
                                if 
                    field.has_key('offset'):
                                    
                    #print "FIELD: " +  str(field['name'][0].encode("UTF-8"))
                                    
                    test = {}
                                    
                    test[field['name'][0].encode("UTF-8")] = str(gb(payloadint(field['offset']), int(field['offset'])+((int(field['bitSize'])+1) / 8)) * (float(field['factor']) if field.has_key('factor') else 1)) + "; " + (field['unit'] if field.has_key('unit') else '')
                                    print (
                    "test: " str(test))
                                    if 
                    printall:
                                        
                    shared test
                                        fp 
                    codecs.open("/tmp/shared.pkl","w"'utf-8')
                                        
                    #fp = codecs.open("shared.pkl","w")
                                        
                    pickle.dump(sharedfp)
                                        
                    fp.close

                            
                    return test 
                    die Ausgabe ist dann:
                    PHP-Code:
                    Source0x4221
                    destination
                    0x0010
                    command
                    0x0100
                    test
                    : {'Temperatur Sensor 1'u'13.1;  \xb0C'}
                    test: {'Temperatur Sensor 2'u'34.8;  \xb0C'}
                    test: {'Temperatur Sensor 3'u'48.5;  \xb0C'}
                    test: {'Temperatur Sensor 4'u'36.1;  \xb0C'}
                    test: {'Drehzahl Pumpe 1'u'0;  %'}
                    test: {'Drehzahl Pumpe 2'u'100;  %'}
                    test: {'Relaismaske''2; '}
                    test: {'Fehlermaske''0; '}
                    test: {'Systemzeit''1337; '}
                    test: {'Schema''9.0; '}
                    test: {'O''0; '}
                    test: {'O''0; '}
                    test: {'O''0; '}
                    test: {'O''0; '}
                    test: {'O''0; '}
                    test: {'O''0; '}
                    test: {'Betriebsstunden Relais 1''1569.0; '}
                    test: {'Betriebsstunden Relais 2''4971.0; '}
                    test: {'Version''1.0; '
                    sieht also meiner Meinung nach gut aus, allerdings kann er die dann gespeicherte Datei nicht lesen:

                    PHP-Code:
                    Unexpected errorresol reading shared.pkl 
                    im Anhang noch die shared.pkl
                    Angehängte Dateien
                    Zuletzt geändert von Marcov; 03.05.2017, 21:30.

                    Kommentar


                      #11
                      Hi ich habe eine Cosmo Regelung und den Dataloger DL2 online alles bei Vbus.net konfiguriert und geht. Ich bekomme eine Fehlermeldung im Smarhome.py (Plugin resol exception: __init__() got an unexpected keyword argument 'port') finde aber nichts mit Port in der init. Was könnte es sein? Danke im Voraus!

                      Kommentar


                        #12
                        Du hast in der etc/plugin.conf einen Parameter namens port definiert, der in der __init__ Methode des Plugins nicht existiert.
                        Viele Grüße
                        Martin

                        There is no cloud. It's only someone else's computer.

                        Kommentar


                          #13
                          Der Port ist in der Smarthome.py nicht relevant, da auskommentiert mit #
                          In der Datei
                          Code:
                          config.py --> IP und Passwort editieren
                          address = ("192.168.178.x", 7053)
                          ist der Port mit 7053 angegeben. Die IP ist ebenfalls noch zu ändern.

                          Kommentar


                            #14
                            ??? In der smarthome.py wird kein Port definiert. Hier finden nur globale Konfigurationen statt.

                            Im Quellcode von smarthome (config.py) sollte man nie editieren!
                            Viele Grüße
                            Martin

                            There is no cloud. It's only someone else's computer.

                            Kommentar


                              #15
                              ..es ist die config.py des Plug-Ins. Das ist nicht sauber - Korrekt.
                              Dieser Kodeschnipsel hat nicht den Anspruch perfekt zu sein - es ist vielmehr ein Provisorium
                              Ich weiß', dass Marcov an einer besseren Lösung arbeitet...

                              Kommentar

                              Lädt...
                              X