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

    #16
    Zitat von Marcov Beitrag anzeigen
    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
    Hi! läuft eigentlich dein Auslesen? Ich bekomme auch nur den Unexpected error: resol reading shared.pkl Fehler. Würde gerne meine Aussentemperatur auf den KNX Bus schicken, hab draußen keine Sensoren. Habe die Cosmo Multi und Datenlogger 2.

    Kommentar


      #17
      hi, ja bei mir läuft es, habe es aber ganz neu ohne die shared -datei geschrieben.
      Ich komme nur gerade nicht dran, da es beim Schwiegervater im Einsatz ist.

      Kommentar


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

        Kommentar


          #19
          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.

          Kommentar


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

            Kommentar


              #21
              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.

              Kommentar


                #22
                Holoman5 SmartHomeNG braucht allgemein Python3...Siehe auch https://github.com/smarthomeNG/smart...--und-Software

                Kommentar


                  #23
                  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.

                  Kommentar


                    #24
                    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!!!

                    Kommentar


                      #25
                      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!!!

                      Kommentar


                        #26
                        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.

                        Kommentar


                          #27
                          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'

                          Kommentar


                            #28
                            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?

                            Kommentar


                              #29
                              Und der Wert in der Visu passt jetzt!!!

                              Kommentar


                                #30
                                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.

                                Kommentar

                                Lädt...
                                X