Ankündigung

Einklappen
Keine Ankündigung bisher.

Smartmeter Plugin - Tester gesucht

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

    #76
    So, ich schaffe es nicht, damit die Stände ausgelesen zu bekommen. Bi zur "Id" funktioniert es. Danach wird nur noch die Baudrate periodisch umgeschaltt.

    Die Schleife "while self.alive and stx == 'False':" macht ja nix anderes, als "ich schreibe so oft den request bis ich was genehmes zurück bekomme" - da liegt doch was im Argen!

    Mit fixer Baudrate funktioniert das ganze momentan nicht (300 > 300 = False). Dafür müsste auch _request[2] entsprechend ausgefüllt werden (kann ja nicht kopiert werden).

    Dann Effizienz: Warum jedes mal neu den seriellen Port komplett neu erzeugen? Warum nicht "not stx" oder "stx == False"? Da sind immer noch Stringvergleiche drin!?

    Kommentar


      #77
      Zitat von Robert Beitrag anzeigen
      Die Schleife "while self.alive and stx == 'False':" macht ja nix anderes, als "ich schreibe so oft den request bis ich was genehmes zurück bekomme" - da liegt doch was im Argen!
      Ja da fehlt ein Punkt zum abschalten (i=2). Ansonsten macht es Sinn das Signal eben etwas später nochmal zu senden falls der Zähler ein hässliches Timing hat.

      Zitat von Robert Beitrag anzeigen
      Mit fixer Baudrate funktioniert das ganze momentan nicht (300 > 300 = False). Dafür müsste auch _request[2] entsprechend ausgefüllt werden (kann ja nicht kopiert werden).
      Ja das habe ich übersehen.

      Zitat von Robert Beitrag anzeigen
      Dann Effizienz: Warum jedes mal neu den seriellen Port komplett neu erzeugen? Warum nicht "not stx" oder "stx == False"? Da sind immer noch Stringvergleiche drin!?
      Weil das erzeugen des seriellen Ports in der init-Methode (warum auch immer) dazu führt das nur der erste Leseversuch nach dem Start funktioniert ... siehe 2 Posts vorher. Stringvergleich - ja hab ich jetzt auch geschnallt.

      So also Sorry nochmal für den commit.
      Umgezogen? Ja! ... Fertig? Nein!
      Baustelle 2.0 !

      Kommentar


        #78
        Hi Mirko,

        sorry, war gerade nur etwas überrascht als ich geupdated habe und beim Probestart das Plugin nicht mehr ging. Bei mir ist "develop" produktiv, da ich sonst immer schalten müsste.

        Ich habe deine Version ja eh auf dem Rechner gehabt und mal versucht das ganze wieder bei mir gangbar zu machen. Vielleicht hast du ja doch noch die Muße das zu probieren. Würde mich freuen:

        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.           https://knx-user-forum.de/
        #########################################################################
        #  DLMS plugin for SmartHome.py.         http://mknx.github.io/smarthome/
        #
        #  This plugin 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.
        #
        #  This plugin 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 this plugin. If not, see <http://www.gnu.org/licenses/>.
        #########################################################################

        import logging
        import time
        import serial
        import re

        logger 
        logging.getLogger('DLMS')

        class 
        DLMS():

            
        def __init__(selfsmarthomeserialportbaudrate="auto"update_cycle="60"use_checksum Truereset_baudrate True):
                
        self._sh smarthome
                self
        ._update_cycle int(update_cycle)
                
        self._use_checksum use_checksum
                self
        ._reset_baudrate reset_baudrate
                self
        ._serialport serialport
                
        if (baudrate.lower() == 'auto'):
                    
        self._baudrate = -1
                
        else:
                    
        self._baudrate int(baudrate)
                
        self._obis_codes = {}
                
        self._request bytearray('\x06000\r\n''ascii')
                
        self._init_seq bytes('/?!\r\n''ascii')
                
        self._serial serial.Serial(self._serialport300bytesize=serial.SEVENBITSparity=serial.PARITY_EVENtimeout=2)

            
        def run(self):
                
        self.alive True
                self
        ._sh.scheduler.add('DLMS'self._update_valuesprio=5cycle=self._update_cycle)

            
        def stop(self):
                
        self.alive False
                self
        ._serial.close()
                
        self._sh.scheduler.remove('DLMS')

            
        def _update_values(self):
                
        logger.debug("dlms: update")
                
        start time.time()
                try:
                    if 
        self._reset_baudrate:
                        
        self._serial.baudrate 300
                    
        #self._serial = serial.Serial(self._serialport, 300, bytesize=serial.SEVENBITS, parity=serial.PARITY_EVEN, timeout=2)
                    
        self._serial.write(self._init_seq)
                    
        self._serial.drainOutput()
                    
        self._serial.flushInput()
                    
        response bytes()
                    
        prev_length 0
                    
        while self.alive:
                        
        response += self._serial.read()
                        
        length len(response)
                        
        # break if timeout or newline-character
                        
        if (length == prev_length) or (response[-1] == 0x0a):
                            break
                        
        prev_length length
                except Exception 
        as e:
                    
        logger.warning("dlms: {0}".format(e))
                
        #logger.warning("dlms: response={}".format(response))
                
        if (len(response) < 5) or ((response[4] - 0x30not in range(6)):
                    
        logger.warning("dlms: malformed response to init seq={}".format(response))
                    return

                if (
        self._baudrate == -1):
                    
        baud_capable 300 * (<< (response[4] - 0x30))
                    
        self._request[2] = response[4]
                    
        logger.debug("dlms: meter returned capability for {} baud".format(baud_capable))
                else:
                    
        baud_capable self._baudrate
                    pow2 
        int(baud_capable 300)
                    
        self._request[2] = 0x30 1
                    
        while (pow2 0):
                        
        pow2 >>= 1
                        self
        ._request[2] += 1
                
        try:
                    
        self._serial.write(self._request)
                    
        self._serial.drainOutput()
                    
        self._serial.flushInput()
                    if (
        baud_capable self._serial.baudrate):
                        
        # change request to set higher baudrate
                        
        logger.debug("dlms: trying to switch to {} baud".format(baud_capable))
                        
        self._serial.baudrate baud_capable
                    response 
        bytes()
                    
        prev_length 0
                    
        while self.alive:
                        
        response += self._serial.read()
                        
        length len(response)
                        if (
        length == prev_length) or (not self._use_checksum and (response[-1] == 0x03)) or ((length 1) and (response[-2] == 0x03)):
                            break
                        
        prev_length length
                except Exception 
        as e:
                    
        logger.warning("dlms: {0}".format(e))
                    return

                
        logger.debug("dlms: reading took: {:.2f}s".format(time.time() - start))
                if 
        self._use_checksum:
                    
        # perform checks (start with STX, end with ETX, checksum match)
                    
        checksum 0
                    
        for i in response[1:]:
                        
        checksum ^= i
                    
        if (len(response) < 5) or (response[0] != 0x02) or (response[-2] != 0x03) or (checksum != 0x00):
                        
        logger.warning("dlms: checksum/protocol error: response={} checksum={}".format(' '.join(hex(i) for i in response), checksum))
                        return
                
        #print(str(response[1:-4], 'ascii'))
                
        for line in re.split('\r\n'str(response[1:-4], 'ascii')):
                    
        # if re.match('[0-9]+\.[0-9]\.[0-9](.+)', line): # allows only
                    # x.y.z(foo)
                    
        if re.match('[0-9]+\.[0-9].+(.+)'line):  # allows also x.y(foo)
                        
        try:
                            
        #data = re.split('[(*)]', line)
                            
        data line.split('(')
                            
        data[1:3] = data[1].strip(')').split('*')
                            if (
        len(data) == 2):
                                
        logger.debug("dlms: {} = {}".format(data[0], data[1]))
                            else:
                                
        logger.debug("dlms: {} = {} {}".format(data[0], data[1], data[2]))
                            if 
        data[0in self._obis_codes:
                                for 
        item in self._obis_codes[data[0]]['items']:
                                    
        item(data[1], 'DLMS''OBIS {}'.format(data[0]))
                        
        except Exception as e:
                            
        logger.warning("dlms: line={} exception={}".format(linee))

            
        def parse_item(selfitem):
                if 
        'dlms_obis_code' in item.conf:
                    
        logger.debug("parse item: {0}".format(item))
                    
        obis_code item.conf['dlms_obis_code']
                    if 
        not obis_code in self._obis_codes:
                        
        self._obis_codes[obis_code] = {'items': [item], 'logics': []}
                    else:
                        
        self._obis_codes[obis_code]['items'].append(item)
                return 
        None 
        Das Neuerzeugen der seriellen Schnittstelle habe ich dir schon mal auskommentiert eingefügt, falls benötigt.

        Ansonsten habe ich den Code für die fixe Baudrate erweitert und die Abbruchbedingung für use_checksum = true eingefügt. Ein Hängen beim zweiten Lesevorgang wird abgefangen. Mit "reset_baudrate" kann verhindert werden, dass weitere init/request wieder mit 300 Baud gesendet werden. Bei mir nimmt er auch 48000 und ist dann logischerweise noch schneller - ist aber wie gesagt dann standardmäßig aus.

        Statt der "sleep" und dem Echo-Canceling habe ich mich mal an drainOutput() und flushInput() versucht - sieht bei mir gut aus - vielleicht hilft das, einige Timingprobleme zu beseitigen?

        Würde mich echt freuen wenn du das noch mal testen könntest!

        Grüße
        Robert

        Kommentar


          #79
          hi,

          sauber!

          mit dem script aus #78 läufts nun super.

          vorher funktionierte nur ca jeder 4te lesevorgang, jetzt ca jeder 2te.

          2013-11-26 17:26:54,316 DEBUG DLMS dlms: Reading took: 4.20s -- __init__.py:_update_values:122

          2013-11-26 17:28:02,816 DEBUG DLMS dlms: Reading took: 12.35s -- __init__.py:_update_values:122
          2013-11-26 17:28:02,828 DEBUG DLMS dlms: 0.0.0 = 00318956 -- __init__.py:_update_values:144
          2013-11-26 17:28:02,834 DEBUG DLMS dlms: 0.1.0 = 00 -- __init__.py:_update_values:144
          2013-11-26 17:28:02,840 DEBUG DLMS dlms: 0.2.0 = 60900000 -- __init__.py:_update_values:144
          2013-11-26 17:28:02,845 DEBUG DLMS dlms: 0.2.2 = 06002200 -- __init__.py:_update_values:144
          2013-11-26 17:28:02,851 DEBUG DLMS dlms: 0.9.1 = 0172737 -- __init__.py:_update_values:144
          2013-11-26 17:28:02,857 DEBUG DLMS dlms: 0.9.2 = 0131126 -- __init__.py:_update_values:144

          2013-11-26 17:28:54,523 DEBUG DLMS dlms: Reading took: 4.20s -- __init__.py:_update_values:122

          2013-11-26 17:30:02,529 DEBUG DLMS dlms: Reading took: 12.35s -- __init__.py:_update_values:122
          2013-11-26 17:30:02,536 DEBUG DLMS dlms: 0.0.0 = 00318956 -- __init__.py:_update_values:144
          2013-11-26 17:30:02,542 DEBUG DLMS dlms: 0.1.0 = 00 -- __init__.py:_update_values:144
          2013-11-26 17:30:02,547 DEBUG DLMS dlms: 0.2.0 = 60900000 -- __init__.py:_update_values:144
          2013-11-26 17:30:02,553 DEBUG DLMS dlms: 0.2.2 = 06002200 -- __init__.py:_update_values:144
          2013-11-26 17:30:02,559 DEBUG DLMS dlms: 0.9.1 = 0172937 -- __init__.py:_update_values:144
          2013-11-26 17:30:02,565 DEBUG DLMS dlms: 0.9.2 = 0131126 -- __init__.py:_update_values:144
          2013-11-26 17:30:02,571 DEBUG DLMS dlms: 1.8.0 = 001849.0 kWh -- __init__.py:_update_values:147

          2013-11-26 17:30:54,261 DEBUG DLMS dlms: Reading took: 4.20s -- __init__.py:_update_values:122

          angepasst hab ich diesmal nichts (auch kein \n vorm string)

          Kommentar


            #80
            Hallo Robert, hier will es nicht. Ich habe mir jeweils mal ein "print(response)" eingebaut. Du siehst es kommt nix, auch ein paar feste sleeps habe ich kurz getestet, für mehr reicht die Zeit heute nicht ich muss noch zur Spätschicht.

            Zwei Sachen:
            - Der Knackpunkt liegt (in meiner Version) in der Schleife die STX prüft. Der kritische Zeitraum liegt zwischen dem Empfang der ID und dem senden des ACKs. Hatte ja schon erwähnt dass ein Zähler ohne ACK z.B. gar nichts macht - da bringt auch eine feste Baudrate nichts ... das muss 100% passen.

            - Die Initialisierung des Ports in der self._update_values brachte folgenden Vorteil an den ich mich jetzt gerade erinnere- mea culpa. War der Port bei __init__ intitalisiert erhielten wir ja nur beim ersten Durchlauf die ID. Bei den folgenden wurde vor der ID noch ein /x07 (BEL) mit ausgegeben, damit fiel dann sowohl bei der Echo-Unterdückung als auch bei der Baudrate alles auf die Nase. Komischerweise taucht das hier jetzt nicht auf, aber wer kann das erklären? Grundsätzlich machen wir doch das gleiche.

            Code:
            2013-11-26 17:25:05,253 DEBUG    DLMS         dlms: update -- __init__.py:_update_values:55
            2013-11-26 17:25:05,755 DEBUG    Scheduler    DLMS next time: 2013-11-26 17:25:20+01:00 -- scheduler.py:_next_time:289
            b'/'
            b'/L'
            b'/LG'
            b'/LGZ'
            b'/LGZ4'
            b'/LGZ4Z'
            b'/LGZ4ZM'
            b'/LGZ4ZMF'
            b'/LGZ4ZMF1'
            b'/LGZ4ZMF10'
            b'/LGZ4ZMF100'
            b'/LGZ4ZMF100A'
            b'/LGZ4ZMF100AC'
            b'/LGZ4ZMF100AC.'
            b'/LGZ4ZMF100AC.M'
            b'/LGZ4ZMF100AC.M2'
            b'/LGZ4ZMF100AC.M23'
            b'/LGZ4ZMF100AC.M23\r'
            2013-11-26 17:25:06,353 DEBUG    DLMS         dlms: meter returned capability for higher baudrate - will request 4800 baud -- __init__.py:_update_values:81
            2013-11-26 17:25:06,355 DEBUG    DLMS         dlms: trying to switch to 4800 baud -- __init__.py:_update_values:95
            b''
            2013-11-26 17:25:08,358 DEBUG    DLMS         dlms: reading took: 3.10s -- __init__.py:_update_values:110
            2013-11-26 17:25:20,289 DEBUG    DLMS         dlms: update -- __init__.py:_update_values:55
            b'/'
            b'/L'
            b'/LG'
            2013-11-26 17:25:20,790 DEBUG    Scheduler    DLMS next time: 2013-11-26 17:25:35+01:00 -- scheduler.py:_next_time:289
            b'/LGZ'
            b'/LGZ4'
            b'/LGZ4Z'
            b'/LGZ4ZM'
            b'/LGZ4ZMF'
            b'/LGZ4ZMF1'
            b'/LGZ4ZMF10'
            b'/LGZ4ZMF100'
            b'/LGZ4ZMF100A'
            b'/LGZ4ZMF100AC'
            b'/LGZ4ZMF100AC.'
            b'/LGZ4ZMF100AC.M'
            b'/LGZ4ZMF100AC.M2'
            b'/LGZ4ZMF100AC.M23'
            b'/LGZ4ZMF100AC.M23\r'
            2013-11-26 17:25:21,309 DEBUG    DLMS         dlms: meter returned capability for higher baudrate - will request 4800 baud -- __init__.py:_update_values:81
            2013-11-26 17:25:21,311 DEBUG    DLMS         dlms: trying to switch to 4800 baud -- __init__.py:_update_values:95
            b''
            2013-11-26 17:25:23,316 DEBUG    DLMS         dlms: reading took: 3.03s -- __init__.py:_update_values:110
            ^C2013-11-26 17:25:25,774 INFO     Main         Number of Threads: 7 -- smarthome.py:stop:348
            2013-11-26 17:25:25,775 INFO     Main         Stop Plugins -- plugin.py:stop:70
            2013-11-26 17:25:26,318 INFO     Main         SmartHome.py stopped -- smarthome.py:stop:372

            Ein anderes Phänomen, vielleicht nicht ganz offtopic und hilft die Sache zu verstehen. Ich hatte das Roomba-Plugin ja auch erst auf serieller Basis und dann auf Sockets umgestellt in der Hoffnung dass ein close dort besser wirkt. Der Roomba hängt an einem Bluetooth Modul und ich wollte da nur Saft rausziehen wenn tatsächlich kommuniziert wird. Wenn ich ein python script in der shell ausführe um die Werte auszulesen sehe ich wie das blinkende Modul auf dauerleuchtend geht und beim beenden des scriptes wieder blinkt. Beim Plugin jedoch bleibt die LED am Modul auf Dauerbetrieb, auch wenn ich close() und del mache (keine exceptions). Beende ich die sh.py Instanz fängt das Modul wieder zu blinken an, also sitzt da noch irgendwas drauf. Kann ein ähnliches Phänomen hier vorliegen?
            Umgezogen? Ja! ... Fertig? Nein!
            Baustelle 2.0 !

            Kommentar


              #81
              Zitat von JuMi2006 Beitrag anzeigen
              Hallo Robert, hier will es nicht. Ich habe mir jeweils mal ein "print(response)" eingebaut. Du siehst es kommt nix, auch ein paar feste sleeps habe ich kurz getestet, für mehr reicht die Zeit heute nicht ich muss noch zur Spätschicht.

              Zwei Sachen:
              - Der Knackpunkt liegt (in meiner Version) in der Schleife die STX prüft. Der kritische Zeitraum liegt zwischen dem Empfang der ID und dem senden des ACKs. Hatte ja schon erwähnt dass ein Zähler ohne ACK z.B. gar nichts macht - da bringt auch eine feste Baudrate nichts ... das muss 100% passen.
              Ok, da muss ich noch mal Überlegen. Deine Antwort auf das Init kommt ja innerhalb von 0,5-0,6s - das ist ok, oder? Und dann kommt einfach gar nix mehr? Wenn man jetzt .timeout oder einen sleep mit 5-10s einfügt immer noch nicht? Denn deine Schleife war ja geduldiger und hatte keinen Timeout. Vielleicht da mal richtig hoch rangehen? Oder meinst du ein "Ack"/(im Code "request"? - nur damit wir vom gleichen reden!?) kann zu früh gesendet werden?

              Zitat von JuMi2006 Beitrag anzeigen
              - Die Initialisierung des Ports in der self._update_values [...] Komischerweise taucht das hier jetzt nicht auf, aber wer kann das erklären? Grundsätzlich machen wir doch das gleiche.
              Durch deinen Commit habe ich mich noch mal mit Echounterdrückung etc auseinander gesetzt: Ich denke .drainOutput() und .flushInput() sorgen da jetzt einfach für einen sauberen Start: Erst warten bis die Senderichtung mit 300 Baud rausgetröpfelt ist, dann Input flushen und damit jedes Echo und anderes Gemüse entsorgen.

              Zitat von JuMi2006 Beitrag anzeigen
              Ein anderes Phänomen, [...] Kann ein ähnliches Phänomen hier vorliegen?
              Verstehe. Der Socket ist sicher durchgängig auf. Warum der nicht geschlossen wird weiß ich auch nicht. Im Fall des eHZ würde ich dass so auch beabsichtigen, beim Roomba kann ich deine Intention auch nachvollziehen und würde dass ggfl. auch so "nachrüsten" wollen. Leider quälen meinen VR100 derzeit Empfangsprobleme (da ich den BT-Dongle umgesteckt habe und ich derzeit auf eine Verison mit Antenne warte) - so dass ich das nicht sofort testen kann.

              Grüße
              Robert

              Kommentar


                #82
                Hallo,

                develop != stable. Develop sollte zwar stabil sein, ist es aber nicht immer.
                Allgemeine Warnung:
                Wer develop auf seinem Produktivsystem einsetzt, sollte in der Lage sein zu einem Zeitpunkt zurück zu gehen bei dem es für ihn stabil läuft. (Ich denke das kann Robert)

                Wer ist denn der "Owner" des Plugins? Der Thread und der ?initiale? Code stammt von Mirko, der Code auf github wurde von Robert eingepflegt.
                Der Owner ist dann für den Code verantwortlich und Änderungen von Dritten sollten über einen Pull-Request realisiert werden.

                Bis bald

                Marcus

                Kommentar


                  #83
                  Zitat von mknx Beitrag anzeigen
                  develop != stable. Develop sollte zwar stabil sein, ist es aber nicht immer.
                  Allgemeine Warnung:
                  Wer develop auf seinem Produktivsystem einsetzt, sollte in der Lage sein zu einem Zeitpunkt zurück zu gehen bei dem es für ihn stabil läuft.
                  Das mit dem develop ist halt eine "komplizierte Sache" die wir wohl etwas unterschiedlich sehen. Wie schon mal in einem anderen Thread dargelegt ist es für Plugin-Entwickler kaum möglich, mit dem stable ihre Grundfunktionalität sicherzustellen. Ich habe nur eine Wärmepumpe, einen VR100, (ok, 3 aber produktive) Squeezeboxen, einen eHZ etc - ich habe ja nicht nebenbei noch einen Testhaushalt.

                  Nur zum Vergleich: Beim dlms-Plugin hatte ich eine (für mich) funktionsfähige Version eingecheckt- bei einer für mich nun nicht mehr funktionierenden Änderung MUSS ich ja irgendwas ändern, wenn ich weiterentwickeln oder einfach um nicht bei jedem Pull dann die Version rückgängig zu machen. Wenn dagegen beim KNX-Plugin die ganze Sause kurzzeitig nicht funktioniert bekommst du hingegen von genug Leuten Bugreports dass du das "freiwillig" behebst. ;-)


                  Zitat von mknx Beitrag anzeigen
                  Wer ist denn der "Owner" des Plugins? Der Thread und der ?initiale? Code stammt von Mirko, der Code auf github wurde von Robert eingepflegt.
                  Der Owner ist dann für den Code verantwortlich und Änderungen von Dritten sollten über einen Pull-Request realisiert werden.
                  Alles richtig. Das Plugin ist halt eine Koproduktion - deswegen war Mirkos Gedanke ja auch nicht abwegig es direkt zu ändern - was eben mit meiner "Betriebsweise des develop" (s.o.) in Konflikt stand. Irgendwie kriegen wir das schon geregelt.

                  Grüße
                  Robert

                  Kommentar


                    #84
                    Zitat von Robert Beitrag anzeigen
                    Oder meinst du ein "Ack"/(im Code "request"? - nur damit wir vom gleichen reden!?) kann zu früh gesendet werden?
                    Genau da liegt das Problem. Das ACK+Baudrate welches von uns gesendet wird darf weder zu früh noch zu spät kommen. Hier glaube ich aber dass sich nicht alle Zähler einig sind wann das ist. Deshalb ist dort auch die Schleife eingebaut. Mein L&G Zähler macht garnichts sofern er nicht zum richtigen Zeitpunkt ein ACK+Baudrate bekommt, da helfen auch keine 10 Sekunden warten.

                    Grundsätzlich stelle ich mir das so vor:

                    > /?!\r\n
                    < echo & id
                    #ggf. echo unterdrücken
                    #id auswerten
                    > init_seq
                    #kurz warten, baudrate umschalten, auf STX checken, ggf baudrate zurück und init_seq neu senden, nach x-Versuchen abbrechen
                    < STX...Data...ETX


                    Zitat von Robert Beitrag anzeigen
                    Start: Erst warten bis die Senderichtung mit 300 Baud rausgetröpfelt ist, dann Input flushen und damit jedes Echo und anderes Gemüse entsorgen.
                    Deswegen wollte ich die Schleife auf STX matchen, das ist das erste Zeichen ohne Echo. Wenn ich ein STX im response habe und die Antwort länger als 1 ist dann hab ich nen echo drin. Daher gibts bei mir das response2 was sich auf die Daten nach der ID bezieht, war erstmal leserlicher im Code.


                    Zitat von Robert Beitrag anzeigen
                    Verstehe. Der Socket ist sicher durchgängig auf. Warum der nicht geschlossen wird weiß ich auch nicht...(da ich den BT-Dongle umgesteckt habe und ich derzeit auf eine Verison mit Antenne warte)
                    Sorry fürs kurze OT, können wir später gerne nochmal aufgreifen. Welcher Dongle? Ich hab mir leider meinen rs232-wifi Adapter gegrillt und würde daher vorerst auch bei Bluetooth bleiben aber: Reichweite mies. Es bleibt sowohl ein socket als auch ein serial offen, damit könnte ich aber im Notfall leben.
                    Umgezogen? Ja! ... Fertig? Nein!
                    Baustelle 2.0 !

                    Kommentar


                      #85
                      Zitat von JuMi2006 Beitrag anzeigen
                      Genau da liegt das Problem. Das ACK+Baudrate welches von uns gesendet wird darf weder zu früh noch zu spät kommen. Hier glaube ich aber dass sich nicht alle Zähler einig sind wann das ist. Deshalb ist dort auch die Schleife eingebaut. Mein L&G Zähler macht garnichts sofern er nicht zum richtigen Zeitpunkt ein ACK+Baudrate bekommt, da helfen auch keine 10 Sekunden warten.
                      Ok, dann bauen wir entweder die Schleife wieder ein oder evtl. könnte man ein Testprogramm machen, was versucht Verzögerungswert, Checksumme etc zu ermitteln? Weil mit EINER Verzögerung muss es ja gehen - dein Zähler wird ja nicht auf die 5 vorher gesendeten Acks bestehen... Muss doch irgendwie gehen!? Bei 300 Baud und 7E1 dauern die 8 Zeichen des Acks ca. 0,25s. Bei deinem Code sind das zzgl. der sleep (2x 0,5) und dem read-timeout beim Warten auf das STX (1s) also ca. 2,25s Granularität.

                      Ich sehe gerade, dass du in dem für deine Zähler funktionierenden Code schon eine Zeitmessung hast - könntest du nicht bitte dort die Zeit messen von "vollständige Antwort auf Init"/Schleifenstart bis "sende Ack", und das IMMER ausgeben, so dass man sieht welches Ack schlussendlich Erfolg (=STX bewirkt) hat?

                      Zitat von JuMi2006 Beitrag anzeigen
                      Sorry fürs kurze OT, können wir später gerne nochmal aufgreifen. Welcher Dongle? Ich hab mir leider meinen rs232-wifi Adapter gegrillt und würde daher vorerst auch bei Bluetooth bleiben aber: Reichweite mies. Es bleibt sowohl ein socket als auch ein serial offen, damit könnte ich aber im Notfall leben.
                      Habe bei der letzten Bestellung leider den hier erwischt: :-(
                      https://weblogs.java.net/blog/alegom...tion_when.html

                      Wenn du nen Tipp hättest für Bluetooth mit externer Antenne und am besten PA/LNA wäre ich auch interessiert...

                      Kommentar


                        #86
                        Es klemmt an der Stelle wo die Baudrate umgestellt wird. Ich benötige davor ein sleep von 0.25, dann kann ich auch sofort nachdem ich die ID habe das ACK senden.

                        Das sollte generell kein Problem sein da lt. specs da für das senden des ACKs bis zu 2 Sekunden passen sollten.

                        Also eigentlich ganz simpel, nen time.sleep(0.25) nachself._serial.write(self._request) und das Problem sollte gelöst sein. Zumindest konnte ich das so bei einem eingrenzen. Der andere mag da noch nciht so recht, da ist das timing wieder kritischer und das versuche ich noch, ich tippe für den kommt das ACK noch zu früh.

                        Versuch mal das:
                        Code:
                        time.sleep (0.5) #Warte auf Zähler
                        self._serial.write(self._request) 
                        time.sleep(0.25) #Pause zw. write und baudwechsel
                        Umgezogen? Ja! ... Fertig? Nein!
                        Baustelle 2.0 !

                        Kommentar


                          #87
                          Zitat von JuMi2006 Beitrag anzeigen
                          Versuch mal das:
                          Code:
                          time.sleep (0.5) #Warte auf Zähler
                          self._serial.write(self._request) 
                          time.sleep(0.25) #Pause zw. write und baudwechsel
                          Bist du so nett und testest mal, ob ein .drainOutput() bei dir anstelle des sleep(0.25) auch funktioniert?

                          Wie oben geschrieben dauert das Senden des Acks bei 300 Baud eben ca. (8 [Byte]*9 [Symbole/Byte])/300 [Symbole/s])=0,24s - das passt sehr gut zu deinem sleep(0.25) und wäre eine Konsequenz daraus, dass eben alles raus sein muss bevor die Baudrate geändert wird, weil es sonst Gemüse gibt. Genau dafür ist das .drainOutput() unabhängig von der Baudrate gedacht und deswegen kann man so auch das Echo recht gut ausblenden: termios.tcdrain - Nullege Python Samples

                          Wenn das ok wäre, bliebe aber doch noch wie vor die Schleife? Oder kann es sein, dass das sleep(0.25) manchmal wegen der Timer-Granularität doch zu knapp ist und du deswegen teilweise mehrere Anläufe brauchst?

                          Viele Grüße
                          Robert

                          Kommentar


                            #88
                            Ich brauche drainOutput und sleep(0.25), hatte das direkt ohne Schleife in deinem letzten Entwurf getestet. Auch das erste sleep(0.5) brauche ich da der nächste Zähler dort sonst das ACK nicht mitbekommt.

                            Also erstmal könnte es so ohne Schleife gehen (dafür eben sleep(0.5)) - zumindest tut es das hier. Wofür ich nicht die Hand ins Feuer legen möchte ist was der übernächste Zähler wieder für Besonderheiten hat. Daher würde ich die Schleife nicht ganz entsorgen bzw. wenigstens einen zweiten Versuch zulassen. Das ist ja nichts weiteres als ein zusätzliches if-statement und 5 Zeilen Code. Dazu müsstest Du aber so umbauen dass auf das STX gewartet wird, das entsorgt das Echo auch gleich mit. Wenn kein STX kommt dann nochmal mit init_seq senden ... sonst break.
                            Umgezogen? Ja! ... Fertig? Nein!
                            Baustelle 2.0 !

                            Kommentar


                              #89
                              Hi Mirko,

                              ich habe jetzt die von dir ermittelten Wartezeiten eingebaut. Da es mit Wartezeiten auch bei mir funktioniert (aber eben 0,75s langsamer) habe ich ein optionales Atttribut "no_waiting" eingebaut, was auch den Verzicht auf die Wartezeiten erlaubt. Standardmäßig wird also gewartet.

                              Ansonsten habe ich im Readme eine kurze Setup-Anleitung verfasst, die Neueinsteigern hoffentlich hilft das Plugin in Betrieb zu nehmen.

                              Grüße
                              Robert

                              Kommentar


                                #90
                                latest stable:

                                Code:
                                2014-01-15 09:08:07,909 ERROR    Main         Plugin dlms exception: __init__() got an unexpected keyword argument 'use_checksum' -- plugin.py:__init__:57
                                Traceback (most recent call last):
                                  File "/usr/local/smarthome/lib/plugin.py", line 53, in __init__
                                    plugin_thread = Plugin(smarthome, plugin, classname, classpath, args)
                                  File "/usr/local/smarthome/lib/plugin.py", line 80, in __init__
                                    exec("self.plugin = {0}.{1}(smarthome{2})".format(classpath, classname, args))
                                  File "<string>", line 1, in <module>
                                TypeError: __init__() got an unexpected keyword argument 'use_checksum'
                                no_waiting hat die gleichen Probleme.

                                wenn ich das rauswerfe sehe ich im Log:
                                Code:
                                2014-01-15 09:12:04,402 DEBUG    DLMS         dlms: Reading took: 4.33s -- __init__.py:_update_values:122
                                2014-01-15 09:12:04,403 WARNING  DLMS         dlms: checksum/protocol error: response=0x2 0x46 0x2e 0x46 0x28 0x30 0x30 0x29 0xd 0xa 0x43 0x2e 0x31 0x28 0x39 0x37 0x33 0x39 0x
                                34 0x37 0x32 0x33 0x24 0x20 0x30 0x20 0x20 0x20 0x20 0x20 0x29 0xd 0xa 0x43 0x2e 0x35 0x2e 0x30 0x28 0x30 0x30 0x29 0xd 0xa 0x31 0x2e 0x38 0x2e 0x30 0x28 0x30 0x31 0x33 0x31 0
                                x35 0x38 0x2e 0x34 0x2a 0x6b 0x57 0x68 0x29 0xd 0xa 0x21 0xd 0xa 0x3 0x44 checksum=20 -- __init__.py:_update_values:132
                                Derzeit zwischen Kistenauspacken und Garten anlegen.
                                Baublog im Profil.

                                Kommentar

                                Lädt...
                                X