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
    Holoman5
    Forums-Einsteiger

  • Holoman5
    antwortet
    Falls es einer braucht für die Cosmo Multi 2 so funktioniert es bei mir.
    Temperatur Item:
    PHP-Code:
    [resol]
    resol_source 0x7821
    resol_destination 
    0x0010
    resol_command 
    0x0100
      
    [[temperature_outside]]
        
    type num
        resol_offset 
    12
        resol_bituse 
    15
        resol_factor 
    0.1
        sqlite 
    yes  
        knx_dpt 
    9
        knx_status 
    0/2/0
        knx_cache 
    0/2/0
        knx_reply 
    0/2/
    und das für die Pumpen:
    PHP-Code:
    [[drehzahl_pumpe_fernwaerme]]
        
    type num
        resol_offset 
    26
        resol_bituse 
    7
        resol_factor 
    1
        sqlite 
    yes  
        knx_dpt 
    5
        knx_status 
    0/3/6
        knx_cache 
    0/3/6
        knx_reply 
    0/3/

    Einen Kommentar schreiben:

  • Holoman5
    Forums-Einsteiger

  • Holoman5
    antwortet
    okay ich setze sie auf 15

    Einen Kommentar schreiben:


  • Marcov
    antwortet
    Hi, nein die Bitsize der Resolausgabe muss nicht identisch mit deinem DPT sein. Die gibt an, welche Bits verwendet werden sollen um daraus den Wert zu erstellen.

    Diese Angabe findest Du, indem Du die XML Datei zu deiner Anlage aus dem Programm "Resol Service Center" anschaust.

    Zitat aus der original Anleitung:
    They are provided in XML by RESOL as part of the RSC (Resol Service Center) download. Just download, install (on linux use wine, it will work) and get the required file for your installation from: {Install_dir}/eclipse/plugins/de.resol.servicecenter.vbus.resol_2.0.0/
    liefert er Dir nun kürzere Werte, wenn Du bituse auf 16, statt 15 stellst?
    Zuletzt geändert von Marcov; 16.11.2017, 16:14.

    Einen Kommentar schreiben:

  • Holoman5
    Forums-Einsteiger

  • Holoman5
    antwortet
    Und der Wert in der Visu passt jetzt!!!

    Einen Kommentar schreiben:

  • Holoman5
    Forums-Einsteiger

  • Holoman5
    antwortet
    Hab es einfach rausgelöscht (=none)
    PHP-Code:
    def __init__(selfsmarthomeipportpasswordcycle=60):
            
    self._sh smarthome
            self
    ._items = []
            
    self._ip ip
            self
    ._port int(port)
            
    self._cycle int(cycle)
            
    self._password password
            self
    ._to_do True 
    Und verstehe ich das vlt. falsch, das DPT 9 hat 2Byte also 16 bit, und daher meine angabe (resol_bituse = 16) richtig so?

    Einen Kommentar schreiben:


  • Marcov
    antwortet
    Hi,

    kannst Du noch mal sagen, was Du in der init.py anpassen musstest (verglichen zu meiner bearbeiteten Version?).
    Password = None greift nur, wenn in der plugin.conf kein password gesetzt ist, macht aber in der Tat keinen Sinn, wenn man zwingend ein Passwort benötigt.
    Bituse gibt an, wieviel Bits für diesen Wert genutzt werden, eine Änderung würde falsche Werte liefern. Wenn Du es auf zwei Kommastellen gerundet haben willst müsstest Du am Ende der parse_payload funktion diese Zeile:
    PHP-Code:
    self._sh.return_item(str(item))(wert,'resol plugin'
    durch diese ersetzen:
    PHP-Code:
    self._sh.return_item(str(item))(round(wert,2),'resol plugin'

    Einen Kommentar schreiben:

  • Holoman5
    Forums-Einsteiger

  • Holoman5
    antwortet
    eine Frage hab ich noch zu mehr Wert (resol_bituse =) was bewirkt der? Auf dem KNX Bus hab ich z.B. 3,4 Grad aber meine Smartvisu zeigt mir 3,4000000000000004 Grad an. Wenn der Wert sich erhöht dann steht z.B. wieder 3,5 in der Visu.

    Einen Kommentar schreiben:

  • Holoman5
    Forums-Einsteiger

  • Holoman5
    antwortet
    So jetzt hat mein KNX Bus auch die Werte!
    PHP-Code:
    [resol]
    resol_source 0x7821
    resol_destination 
    0x0010
    resol_command 
    0x0100
      
    [[temperature_solar_outside]]
        
    type num
        resol_offset 
    12
        resol_bituse 
    16
        resol_factor 
    0.1
        sqlite 
    yes  
        knx_dpt 
    9
        knx_send 
    0/2/0
        knx_reply 
    0/2/
    Muss das Item nur noch umbenennen auf Aussentemepratur!

    Nochmal großen Dank an Marcov!!!! saubere Leistung!!!

    Einen Kommentar schreiben:

  • Holoman5
    Forums-Einsteiger

  • Holoman5
    antwortet
    Zitat von Marcov Beitrag anzeigen

    Hi, sorry müsste jetzt gehen, in line 96 waren zu viele Leerzeichen vor der Funktion load_data, habe ich oben editiert.
    Vielen Dank! Es läuft nun mit meiner Cosmo Multi und dem DL2. Nach copy&paste waren es 3 Leerzeilen, habe eine hinzugefügt dann kam ich weiter. Nun kam (Vbus Lan is not ready, reply: -ERROR: Not authorized to start data mode) im DL2 war das Fernzugriff pw auf vbus gestanden das habe ich auf admin geändert und in der init password=none auf password geändert. Nach reboot alles da!!!!! Jetzt muss ich das nur richtig auf den KNX Bus schicken!!!

    Einen Kommentar schreiben:


  • Marcov
    antwortet
    Zitat von Holoman5 Beitrag anzeigen
    Habs gleich mal ausprobiert bekomme diesen Fehler: Plugin resol exception: unindent does not match any outer indentation level (__init__.py, line 96)
    Hi, sorry müsste jetzt gehen, in line 96 waren zu viele Leerzeichen vor der Funktion load_data, habe ich oben editiert.

    Einen Kommentar schreiben:


  • psilo
    antwortet
    Holoman5
    Forums-Einsteiger
    Holoman5 SmartHomeNG braucht allgemein Python3...Siehe auch https://github.com/smarthomeNG/smart...--und-Software

    Einen Kommentar schreiben:

  • Holoman5
    Forums-Einsteiger

  • Holoman5
    antwortet
    ich hab Python 2.7.9 installiert auf dem smarthome.py Server. Brauch ich die 3.x Version? weil da in der init was von 3 steht oben. Sorry bin nicht so gut in Python.

    Einen Kommentar schreiben:

  • Holoman5
    Forums-Einsteiger

  • Holoman5
    antwortet
    Habs gleich mal ausprobiert bekomme diesen Fehler: Plugin resol exception: unindent does not match any outer indentation level (__init__.py, line 96)

    Einen Kommentar schreiben:


  • Marcov
    antwortet
    so, habe noch was gefunden, müsste gehen, ist aber nicht aufgeräumt. Die Aussage "ganz neu" ist etwas anmaßend, es ist eine angepasste Version von Khome, die config und json Dateien werden nicht mehr benötigt, das wird in den Items definiert. Es wird auch keine "Zwischendatei" mehr verwendet:

    init.py:
    PHP-Code:
    #!/usr/bin/env python3
    # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab
    #########################################################################
    # Copyright 2013 KNX-User-Forum e.V.          http://knx-user-forum.de/
    #########################################################################
    #  This file is part of SmartHome.py.    http://mknx.github.io/smarthome/
    #
    #  SmartHome.py is free software: you can redistribute it and/or modify
    #  it under the terms of the GNU General Public License as published by
    #  the Free Software Foundation, either version 3 of the License, or
    #  (at your option) any later version.
    #
    #  SmartHome.py is distributed in the hope that it will be useful,
    #  but WITHOUT ANY WARRANTY; without even the implied warranty of
    #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    #  GNU General Public License for more details.
    #
    #  You should have received a copy of the GNU General Public License
    #  along with SmartHome.py. If not, see <http://www.gnu.org/licenses/>.
    #########################################################################

    import socket
    import logging
    import time

    logger 
    logging.getLogger(__name__)

    class 
    Resol():

        
    def __init__(selfsmarthomeipportpassword=Nonecycle=60):
            
    self._sh smarthome
            self
    ._items = []
            
    self._ip ip
            self
    ._port int(port)
            
    self._cycle int(cycle)
            
    self._password password
            self
    ._to_do True

        def run
    (self):
            
    #logging.warning("run function")
            
    self.alive True
            self
    ._sh.scheduler.add('sock'self.sockprio=5cycle=self._cycleoffset=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
    (selfitem):
            if 
    'resol_offset' in item.conf:
              
    logger.debug("ELTERN Source: " str(item.return_parent().conf['resol_source']))
              if 
    'resol_bituse' in item.conf:
                
    self._items.append(item)
                return 
    self.update_item
              
    else:
                
    logger.error("resol_offset found in: " str(item) + " but no bitsize given, specify bitsize in item with resol_bitsize = ")

        
    def update_item(selfitemcaller=Nonesource=Nonedest=None):
            
    #logging.warning("update function")
            
    if caller != 'Resol':
              
    #logger.info("update item: {0}".format(item.id()))
              
    value str(int(item()))

        
    def sock(self):
            
    self.sock socket.socket(socket.AF_INETsocket.SOCK_STREAM)
            
    self.sock.connect((self._ipself._port))
            
    #self.result = dict()
            
    self.login()
            
    self.load_data()
            try:
              
    self.sock.shutdown(0)
            
    except:
              
    pass
            self
    .sock.close()
            
    self.sock None

    # Logs in onto the DeltaSol BS Plus over LAN. Also starts (and maintains) the
    # actual stream of data.
        
    def login(self):
            
    dat self.recv()
            
    #logger.debug("DATA: " + str(dat))

            #Check if device answered
            
    if dat != "+HELLO\n":
              
    logger.warning("WRONG REPLY FROM VBUS LAN: " str(dat))
              return 
    False

            
    #Send Password
            
    self.send("PASS %s\n" self._password)

            
    dat self.recv()
            
    #logger.debug("DATA 2: " + str(dat))

            
    return dat.startswith("+OK")

       
    def load_data(self):
            
    #Request Data
            
    global new_data
            self
    .send("DATA\n")
            
    dat self.recv()

            
    #Check if device is ready to send Data
            
    if not dat.startswith("+OK"):
              
    logger.warning("Vbus Lan is not ready, reply: " str(dat))
              return
            
    buf self.readstream()
            
    msgs self.splitmsg(buf)
            
    #for msg in msgs:
              #if "PV1" == self.get_protocolversion(msgs):
                #self.parse_payload(msgs)
            
    if "PV1" == self.get_protocolversion(msgs[0]):
              
    self.parse_payload(msgs[0])  

        
    # Receive 1024 bytes from stream
        
    def recv(self):
            
    dat self.sock.recv(1024).decode('Cp1252')
            return 
    dat

        
    # Sends given bytes over the stream. Adds debug
        
    def send(selfdat):
            
    self.sock.send(dat.encode('utf-8'))

        
    # Read Data until minimum 1 message is received
        
    def readstream(self):
            
    data self.recv()
            while 
    data.count(chr(0xAA)) < 4:
              
    data += self.recv()
            return 
    data

        
    #Split Messages on Sync Byte
        
    def splitmsg(selfbuf):
            return 
    buf.split(chr(0xAA))[1:-1]

        
    # Format 1 byte as String
        
    def format_byte(selfbyte):
            return 
    hex(ord(byte))[0:2] + '0' hex(ord(byte))[2:] if len(hex(ord(byte))) < else hex(ord(byte))

        
    # Extract protocol Version from msg
        
    def get_protocolversion(selfmsg):
            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 NOT USED AT THE MOMENT
        
    def get_destination(selfmsg):
            return 
    self.format_byte(msg[1]) + self.format_byte(msg[0])[2:]

        
    #Extract source from msg NOT USED AT THE MOMENT
        
    def get_source(selfmsg):
            return 
    self.format_byte(msg[3]) + self.format_byte(msg[2])[2:]

        
    # Extract command from msg NOT USED AT THE MOMENT
        
    def get_command(selfmsg):
            return 
    self.format_byte(msg[6]) + self.format_byte(msg[5:6])[2:]

        
    # Get count of frames in msg
        
    def get_frame_count(selfmsg):
            return 
    self.gb(msg78)

        
    # Extract payload from msg
        
    def get_payload(selfmsg):
            
    payload ''
            
    for i in range(self.get_frame_count(msg)):
              
    payload += self.integrate_septett(msg[9+(i*6):15+(i*6)])
            return 
    payload

        
    # parse payload and set item value
        
    def parse_payload(selfmsg):
            
    command self.get_command(msg)
            
    source self.get_source(msg)
            
    destination self.get_destination(msg)
            
    logger.debug("command: " str(command))
            
    logger.debug("source: " str(source))
            
    logger.debug("destination: " str(destination))
            
    payload self.get_payload(msg)
            for 
    item in self._items:
                if 
    'resol_source' in item.return_parent().conf:
                    if 
    item.return_parent().conf['resol_source'] != self.get_source(msg):
                        
    logger.debug("source if item " str(item) + " does not match msg source " str(item.return_parent().conf['resol_source']) + " not matches msg source: " str(self.get_source(msg)))
                        continue
                if 
    'resol_destination' in item.return_parent().conf:
                    if 
    item.return_parent().conf['resol_destination'] != self.get_destination(msg):
                        
    logger.debug("destination if item " str(item) + " does not match msg destination " str(item.return_parent().conf['resol_destination']) + " not matches msg destination: " str(self.get_destination(msg)))
                        continue
                if 
    'resol_command' in item.return_parent().conf:
                    if 
    item.return_parent().conf['resol_command'] != self.get_command(msg):
                        
    logger.debug("destination if item " str(item) + " does not match msg destination " str(item.return_parent().conf['resol_command']) + " not matches msg destination: " str(self.get_command(msg)))
                        continue
                
    end int(item.conf['resol_offset']) + (int(item.conf['resol_bituse']) + 1) / 8
                
    #logger.debug("Start: " + str(item.conf['resol_offset']) + " ENDE: " + str(end))
                
    wert self.gb(payloadint(item.conf['resol_offset']), int(end)) * float(item.conf['resol_factor'] if 'resol_factor' in item.conf else 1)
                
    logger.debug("payload: of item " str(item) + ": " str(wert))
                
    self._sh.return_item(str(item))(wert,'resol plugin')

        
    def integrate_septett(selfframe):
            
    data ''
            
    septet ord(frame[4])

            for 
    j in range(4):
              if 
    septet & (<< j):
                  
    data += chr(ord(frame[j]) | 0x80)
              else:
                  
    data += frame[j]

            return 
    data

        
    # Gets the numerical value of a set of bytes (respect Two's complement by value Range)
        
    def gb(selfdatabeginend):  # GetBytes
            
    wbg sum([0xff << (8) for ib in enumerate(data[begin:end])])
            
    sum([ord(b) << (8) for ib in enumerate(data[begin:end])])


            if 
    >= wbg/2:
              
    = -* (wbg s)
            return 

    beispiel item.conf
    destination, command und source müssen nur im überordneten Item angegben werden und werden für alle Childrenitems verwendet. Die entsprechenden Daten findet ihr hier.
    https://danielwippermann.github.io/r...s-packets.html

    Ihr müsst dann noch das Programm Resol Service Center installieren, um dort die offset und Bituse auslesen zu können:
    They are provided in XML by RESOL as part of the RSC (Resol Service Center) download. Just download, install (on linux use wine, it will work) and get the required file for your installation from: {Install_dir}/eclipse/plugins/de.resol.servicecenter.vbus.resol_2.0.0/

    PHP-Code:
    [resol]
    resol_source 0x4221
    resol_destination 
    0x0010
    resol_command 
    0x0100
      
    [[temperature_1]]
        
    type num
        resol_offset 
    0
        resol_bituse 
    15
        resol_factor 
    0.1
        sqlite 
    yes 
    plugin.conf:
    PHP-Code:
    [resol]
        
    class_name Resol
        class_path 
    plugins.resol
        ip 
    "XXXX" # ip of VBUS LAN
        
    cycle 60
        port 
    7053       # port of VBUS LAN usualy is 7053!
        
    password 'XXXX' 
    Zuletzt geändert von Marcov; 16.11.2017, 16:14.

    Einen Kommentar schreiben:

  • Holoman5
    Forums-Einsteiger

  • Holoman5
    antwortet
    Bo das wär echt eine coole Sache wenn du es hier posten oder mir zukommen lassen könntest demnächst!

    Einen Kommentar schreiben:

Lädt...
X