Ankündigung

Einklappen
Keine Ankündigung bisher.

Plugin Xiaomi Saugroboter

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

    #61
    Super, danke für den Tip.
    Funktioniert nun auch, die items kommen an, passt.
    Nur bei manchen bin ich mir nicht sicher, was die bedeuten sollen bzw. ob die richtig ankommen...

    z.B.:
    - es fehlt bei statistik.reinigungsdetailsX die letzte Reinigung.
    - der Wert von statistik.gesamtlaufzeit ist etwas komplett merkwürdiges
    - die stundenzaehler stimmen alle irgendwie nicht so recht

    Muss das plugin nun mal in Ruhe testen

    Kommentar


      #62
      Zitat von Bonze Beitrag anzeigen
      ja, habs im github geändert heut morgen, da war eine abfrage vorgeschaltet, die hatte ich mal reingemacht.. hab sie auskommentiert...


      HTML-Code:
      <div class="center">
      <div class="set-2" data-role="collapsible-set" data-theme="c" data-content-theme="a" data-mini="true">
      <div data-role="collapsible" data-collapsed="false">
      <h3>
      Status Saugsaugroboterter
      </h3>
      <div align="left">
      <b>Zustand: </b></br>
      Ladezustand:{{ icon.battery('icon12', '', 'saugroboter.live.batterie_status','0','100') }} {{ basic.value('batt', 'saugroboter.live.batterie_status') }}% |
      Lüftergeschwindigkeit: {{ icon.volume('luefterspeed', 'saugroboter.einstellungen.luefter_speed','0','100') }}
      {% if saugroboter.live.reinigt %}
      <b>Saugroboterter reinigt:</b></br>
      
      Fläche gereinigt: {{ basic.value('qmlive', 'saugroboter.live.area') }} |
      Reinigt schon: {{ basic.value('timelive', 'saugroboter.live.reinigungszeit', 'h') }} |
      Lüftergeschwindigkeit: {{ icon.volume('luefterspeed1', 'saugroboter.einstellungen.luefter_speed','0','100') }} |
      
      {{ robvac.carpet('carpetmode', 'saugroboter.live.carpetmode_enabled', 'saugroboter.live.carpetmode_low', 'saugroboter.live.carpetmode_integral', 'saugroboter.live.carpetmode_high') }}
      
      {% elseif saugroboter.live.errorcode != '' %}
      {{ basic.text('err', 'saugroboter.live.errorcode', 'saugroboter.live.errorcode', '') }}
      {% elseif saugroboter.live.dnd_status %}
      DND Modus aktiv
      {% elseif 'Charging' in saugroboter.live.zustand %}
      Saugroboter ist in der Ladestation
      {% elseif 'Pause' in saugroboter.live.zustand %}
      Reinigung pausiert
      {% elseif 'Charger disconnected' in saugroboter.live.zustand %}
      saugroboterter steht irgendwo?
      {% elseif 'Pause' in saugroboter.live.zustand %}
      saugroboterter pausiert
      {% endif %}
      </div>
      <hr>
      <div >
      <div style="float:right; background-image:url(pages/hollaender/pics/sauger.png); opacity: 0.7; border-radius: 4px; z-index: 0; width: 180px; height: 150px;">
      
      </div>
      <div align="left">
      <b>Steuerung:</b>
      {{ basic.dual('start', saugroboter.befehl.start, 'audio_play.svg', 'audio_play.svg', '1') }}
      {{ basic.dual('stop', saugroboter.befehl.stop, 'audio_stop.svg', 'audio_stop.svg') }}
      {{ basic.dual('pause', saugroboter.befehl.pause, 'audio_pause.svg', 'audio_pause.svg') }}
      {{ basic.button('home', 'saugroboter.befehl.basis','', 'home', '0', 'mini') }}
      {{ basic.button('zone', 'saugroboter.befehl.spot_clean', 'Zone','', '0', 'mini') }}
      {{ basic.button('find', 'saugroboter.befehl.set_find', '? find ?','', '0', 'mini') }}
      <hr>
      
      
      
      <b>Gesamt:</b></bR>
      Fläche: {{ basic.value('qm', 'saugroboter.statistik.gereinigte_flaeche', 'm²') }} | Anzahl Reinigungen: {{ basic.value('anzsahl', 'saugroboter.statistik.anzahl_reinigungen') }} |
      Laufzeit: {{ basic.value('reinigungszeit', 'saugroboter.statistik.gesamtlaufzeit', 'h')}}</br>
      <b>Zeit Verbleibend:</b></bR>
      Bürste Seite: {{ basic.value('b_side', 'saugroboter.stundenzaehler.buerste_seite_verbleibend', 'h') }} | Hauptbürste: {{ basic.value('b_haupt', 'saugroboter.stundenzaehler.buerste_haupt_verbleibend', 'h') }} |
      Filter: {{ basic.value('filterzeit', 'saugroboter.stundenzaehler.filter_verbleibend', 'h') }} | Sensor: {{ basic.value('sensorzeit', 'saugroboter.stundenzaehler.sensor_reinigen_verbleibend', 'h') }}</br>
      </div>
      
      </div>
      </div>
      so sieht mein Anzeige Code aus..
      aber jetzt ein widget draus zaubern .. das ist schwieriger als ich dachte.. vorallem, weil es so viele verschiedene Items sind..

      Funktioniert die Anzeige bei dir sauber?
      Also die Fallunterscheidung beim Status in saugroboter.live.zustand funktioniert bei mir überhaupt nicht, das liefert nur Fehler bzw. Nicht-Treffer...
      Und könntest du das Hintergrundbild vielleicht zur Verfügung stellen?


      edit:
      Bei mir werden irgendwie nicht alle Werte sauber aktualisiert.
      Ich habe bisher folgende Werte gefunden, welche nicht passen:
      - 'xiaomi_roborock.live.reinigt'
      - 'xiaomi_roborock.live.aktiv'
      - 'xiaomi_roborock.live.gereinigt'
      - 'xiaomi_roborock.live.reinigungszeit'
      - 'xiaomi_roborock.live.pausiert'
      Funktioniert das bei euch?


      edit2:
      Hiermit hab ich die Anzeige nun erstmal hinbekommen:
      HTML-Code:
                      <b>Zustand: </b></br>
                      Batterie: {{ icon.battery('battery_state', '', 'xiaomi_roborock.live.batterie_status', '0', '100') }}  {{ basic.value('batt', 'xiaomi_roborock.live.batterie_status') }}%&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;
                      Lüfter:   {{ icon.volume('luefterspeed', '', 'xiaomi_roborock.einstellungen.luefter_speed', '0', '100') }}
                      </br>
                      {% if xiaomi_roborock.live.reinigt == 1 %}
                          <hr>
                          <b>Saugroboter reinigt:</b></br>
                          Fläche gereinigt: {{ basic.value('qmlive', 'xiaomi_roborock.live.flaeche', 'qm') }} |
                          Reinigt schon: {{ basic.value('timelive', 'xiaomi_roborock.live.reinigungszeit', 'h') }} |
                          Lüftergeschwindigkeit: {{ basic.value('luefterspeed1', 'xiaomi_roborock.einstellungen.luefter_speed') }}% |
                          {{ robvac.carpet('carpetmode', 'xiaomi_roborock.live.carpetmode_enabled', 'xiaomi_roborock.live.carpetmode_low', 'xiaomi_roborock.live.carpetmode_integral', 'xiaomi_roborock.live.carpetmode_high') }}
                      {% elseif xiaomi_roborock.live.errorcode != '' %}
                          {{ basic.text('err', 'xiaomi_roborock.live.errorcode', 'xiaomi_roborock.live.errorcode', '') }}
                      {% elseif xiaomi_roborock.live.dnd_status == 1 %}
                          DND Modus aktiv
                      {% elseif ('Charging' in xiaomi_roborock.live.zustand) == True %}
                          Saugroboter ist in der Ladestation
                      {% elseif ('Pause' in xiaomi_roborock.live.zustand) == True %}
                          Reinigung pausiert ???
                      {% elseif ('Charger disconnected' in xiaomi_roborock.live.zustand) == True %}
                          Saugroboter steht irgendwo?
                      {% endif %}
      Zuletzt geändert von Gue0411; 12.12.2019, 11:45.

      Kommentar


        #63
        ok also im Anhang mal wie die Darstellung bei mir ist.
        mit diesem Code

        Ichn habe den Roborock s2? also den ohne Wischfunktion und nutze Smartvisu 2.9 Smarthomeng1.6

        Code:
        <div class="center">
              <div class="set-2" data-role="collapsible-set" data-theme="c" data-content-theme="a" data-mini="true">
                <div data-role="collapsible" data-collapsed="false">
                  <h3>
                    Status Saugroboter
                  </h3>
                <div align="left">
                    <b>Zustand: </b></br>
                    {% if saugroboter.live.reinigt  %}
                            <b>saugroboterter reinigt:</b></br>
                            Fläche geschafft: {{ basic.value('qmlive', 'saugroboter.live.area') }} |
                            Reinigt schon: {{ basic.value('timelive', 'saugroboter.live.reinigungszeit', 'h') }} |
                            Lüftergeschwindigkeit: {{ basic.value('luefterspeed', 'saugroboter.einstellungen.luefter_speed') }} |
                            
                            {{ robvac.carpet('carpetmode', 'saugroboter.live.carpetmode_enabled', 'saugroboter.live.carpetmode_low', 'saugroboter.live.carpetmode_integral', 'saugroboter.live.carpetmode_high') }}
                            
                            {% if saugroboter.live.carpetmode_enabled %}
                                Teppichmodus:
                                    {% if saugroboter.live.carpetmode_low %}
                                        <img class="icon" src="{{ icon0 }}control_1.svg" />
                                    {% endif %}
                                    {% if saugroboter.live.carpetmode_integral %}
                                        <img class="icon" src="{{ icon0 }}control_2.svg" />
                                    {% endif %}
                                    {% if saugroboter.live.carpetmode_high %}
                                        <img class="icon" src="{{ icon0 }}control_3.svg" />
                                    {% endif %}
                                    </bR>
                            {% endif %}
                    {% elseif saugroboter.live.errorcode != ''%}
                         {{ basic.text('err', 'saugroboter.live.errorcode', 'saugroboter.live.errorcode', '') }}
                    {% elseif saugroboter.live.dnd_status %}
                        DND Mode
                    {% elseif 'Charging' in saugroboter.live.zustand %}
                        saugroboterter at Home, Laden
                        {{ basic.value('batt', 'saugroboter.live.batterie_status') }} %
                        {% if 'saugroboter.live.batterie_status' < '25' %}
                            <img class="icon icon1" src="{{ icon0 }}measure_battery_0.svg" />
                        {% elseif 'saugroboter.live.batterie_status' >= '25' and 'saugroboter.live.batterie_status' < '50'%}
                            <img class="icon" src="{{ icon0 }}measure_battery_25.svg" />
                        {% elseif 'saugroboter.live.batterie_status' >= '50' and 'saugroboter.live.batterie_status' < '75'%}
                            <img class="icon" src="{{ icon0 }}measure_battery_50.svg" />
                        {% elseif 'saugroboter.live.batterie_status' >= '75' and 'saugroboter.live.batterie_status' < '100'%}
                            <img class="icon" src="{{ icon0 }}measure_battery_75.svg" />
                        {% else %}
                            <img class="icon icon2" src="{{ icon0 }}measure_battery_100.svg" />
                        {% endif %}
                        
                    {% elseif 'Charger disconnected' in saugroboter.live.zustand %}    
                        saugroboterter steht irgendwo?
                    {% elseif Pause in saugroboter.live.zustand %}
                        saugroboterter pausiert
                    {% endif %}
                </div>
                <hr>
                <div >
                    <div style="float:right; background-image:url(pages/hollaender/pics/sauger.png); opacity: 0.7; border-radius: 4px; z-index: 0; width: 180px; height: 150px;">
                        
                    </div>
                    <div align="left">
                        <b>Steuerung:</b>
                        {{ icon.battery('icon2', 'batt', 'saugroboter.live.batterie_status') }}</br>
        
                        {{ basic.dual('start', saugroboter.befehl.start, 'audio_play.svg', 'audio_play.svg', '1') }}
                        {{ basic.dual('stop', saugroboter.befehl.stop, 'audio_stop.svg', 'audio_stop.svg') }}
                        {{ basic.dual('pause', saugroboter.befehl.pause, 'audio_pause.svg', 'audio_pause.svg') }}
                        {{ basic.button('home', 'saugroboter.befehl.basis','', 'home', '0', 'mini') }}
                        {{ basic.button('zone', 'saugroboter.befehl.spot_clean', 'Zone','', '0', 'mini') }}
                        {{ basic.button('find', 'saugroboter.befehl.set_find', '? find ?','', '0', 'mini') }}
                        <hr>    
                                    
                    
                        
                        <b>Gesamt:</b></bR>
                        Fläche: {{ basic.value('qm', 'saugroboter.statistik.gereinigte_flaeche', 'm²') }} | Anzahl Reinigungen: {{ basic.value('anzsahl', 'saugroboter.statistik.anzahl_reinigungen') }} |
                        Laufzeit: {{ basic.value('reinigungszeit', 'saugroboter.statistik.gesamtlaufzeit', 'h')}}</br>
                        <b>Zeit Verbleibend:</b></bR>
                        Bürste Seite: {{ basic.value('b_side', 'saugroboter.stundenzaehler.buerste_seite_verbleibend', 'h') }} | Hauptbürste: {{ basic.value('b_haupt', 'saugroboter.stundenzaehler.buerste_haupt_verbleibend', 'h') }} |
                        Filter: {{ basic.value('filterzeit', 'saugroboter.stundenzaehler.filter_verbleibend', 'h') }} | Sensor: {{ basic.value('sensorzeit', 'saugroboter.stundenzaehler.sensor_reinigen_verbleibend', 'h') }}</br>
                    </div>
        
                </div>
              </div>

        was sagt denn dein Backend? http://SMARTHOMENGIP:8383/xiaomi_vac/ ??
        kommen da die Werte an ?
        Angehängte Dateien

        Kommentar


          #64
          Ich habe den Roborock S50 mit Wischfunktion.
          SmarthomeNG ist bei mir 1.5.1 und SmartVisu 2.8.


          Im Webinterface stehen die Werte leider auch nicht, ich bekomme also die gleichen Werte wie in den items.
          Kann ich die "Rohwerte", also die die das Plugin direkt aus dem Sauger ausliest, irgendwie auslesen, damit ich vergleichen kann, was hier nicht stimmt?


          Wegen der Fallunterscheidung beim Status:
          Also ich muss bei mir alles in Klammern setzen und auf true abfragen, ansonsten bekomme ich hier keinerlei Anzeige!
          Bei dir steht:
          Code:
          {% elseif 'Charging' in xiaomi_roborock.live.zustand %}
          Ich muss das hier schreiben:
          Code:
          {% elseif ('Charging' in xiaomi_roborock.live.zustand) == True %}

          Kommentar


            #65
            Hast du denn das Token auch ausgelesen und richtig eingetragen ? Du kannst über die konsole, die werte der mirobo bibliothek direkt abrufen, wie das geht, steht in der mirobo doku

            Kommentar


              #66
              Ja, das token passt.
              Auch in der Konsole kann ich die Verbindung problemlos herstellen. Sowohl der handshake als auch das manuelle abfragen funktioniert!

              Bei den consumables bekomme ich z.B. das hier in der Konsole:
              Code:
              Main brush:   9 days, 19:27:38 (left 2 days, 16:32:22)
              Side brush:   21:18:18 (left 7 days, 10:41:42)
              Filter:       3 days, 11:13:29 (left 2 days, 18:46:31)
              Sensor dirty: 3:48:26 (left 1 day, 2:11:34)
              In den items kommen dann aber immer nur die Stunden davon an.
              Also am Beispiel der Hauptbürste steht dann im item nur verbraucht '19' (statt 9 Tage, 19h) und übrig noch '16' (statt 2 Tage, 16h).



              In der Anzeige, also der Fallunterscheidung des Zustandes steht bei mir gerade "Saugroboter ist in der Ladestation", obwohl das item "Charger disconnected" sagt...



              In besagten items, welche leer sind, also z.B. Reinigungszeit steht bei mir aktuell nur eine "0", obwohl über die Konsole "1:03:57" kommt.

              Kommentar


                #67
                Mhdie restzeitangaben werden beim auslesen gerundet, vl is da der fehler .. kann erst ende der woche wieder genauer gucken, liege hier in lanzarote am strand und hab nur das handy dabei,.. ausser du guckst mal ma den code, bei read(), dass round müsstest du auskommentieren können

                Kommentar


                  #68
                  Also bei den Zeiten musste ich immer
                  Code:
                  duration.seconds
                  durch
                  Code:
                  duration.total_seconds()
                  ersetzen.


                  PS: schönen Urlaub

                  Kommentar


                    #69
                    Ok Ok , ansonsten kannst du den html code ja auch anpassen und deine version hier mal veröffentlichen

                    Kommentar


                      #70
                      Die Reinigungszeiten passen nun mit den Anpassungen, allerdings habe ich noch Probleme mit dem "complete":
                      Code:
                      self._data['last0_complete'] =      self._data['clean_details_last0'][0].complete
                      Hier wird mir immer false angezeigt.
                      Wenn ich mit das item ansehe, dann steht da bei Update und vorheriger Wert interessantes drin:
                      Code:
                      vorheriger Wert       true
                      vorh. Alter (Update)  0.00 Sekunden
                      Update durch          Robvac
                      Sieht für mich irgendwie aus, als käme der Wert richtig an, wird dann aber nochmals überschrieben, warum auch immer...?!

                      Interessant ist an der Stelle noch, ich hab mir eine Logik in SHNG erstellt, welche das Plugin nachbildet.
                      Hier bekomme ich die Werte sauber übergeben!



                      Hab das init.py mittlerweile ein wenig angepasst, hier mein Stand:
                      Code:
                      #
                      #!/usr/bin/env python3
                      # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab
                      #
                      ####################################################################################
                      ######################################################################################
                      #
                      #  Copyright 2018 Version-1    Manuel Holländer
                      #  Copyright 2019 Version-2    Manuel Holländer
                      ####################################################################################
                      #
                      #  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.
                      #
                      #  smarthomeNG 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/>.
                      #
                      ####################################################################################
                      #
                      #   VERSION - 2
                      #
                      ####################################################################################
                      #
                      import logging
                      import threading
                      import struct
                      import binascii
                      import re
                      import time
                      from datetime import datetime
                      
                      import miio
                      from miio.vacuum import Vacuum, VacuumException
                      from miio.vacuumcontainers import (VacuumStatus, ConsumableStatus, DNDStatus, CleaningDetails, CleaningSummary, Timer)
                      from miio.discovery import Discovery
                      
                      from lib.model.smartplugin import *
                      from lib.module import Modules
                      from lib.item import Items
                      
                      class Robvac(SmartPlugin):
                          ALLOW_MULTIINSTANCE = False
                          PLUGIN_VERSION="0.4.1.2"
                          
                          def __init__(self, smarthome,ip='127.0.0.1', token='', read_cycle=20):
                              self._ip = str(ip)
                              self._token = str(token)
                              self._cycle = int(read_cycle)
                              self._sh = smarthome
                              self.logger = logging.getLogger(__name__)
                              
                              self.messages = {}
                              self.found = False
                              self._lock = threading.Lock()
                              self.retry_count_max = 3
                              self.retry_count = 1
                              self._connected = False
                              self._data = {}
                              if not self.init_webinterface():
                                  self._init_complete = False
                                  
                              if self._token == '':
                                  self.logger.error("Xiaomi_Robvac: No Key for Communication given, Plugin would not start!")
                                  pass
                              else:
                                  self.logger.debug("Xiaomi_Robvac: Plugin Start!")
                                  if self._cycle > 10:
                                      self._sh.scheduler.add('Xiaomi_Robvac Read cycle', self._read, prio=5, cycle=self._cycle)
                                  else:
                                      self.logger.warning("Xiaomi_Robvac: Read Cycle is to fast! < 10s, not starting!")
                          # ----------------------------------------------------------------------------------------------
                          # Verbinden zum Roboter
                          # ----------------------------------------------------------------------------------------------
                          def _connect(self):        
                                  if self._connected == False:
                                      for i in range(0,self.retry_count_max-self.retry_count):
                                          try:
                                              self.vakuum = miio.Vacuum(self._ip,self._token, 0, 0)
                                              self.retry_count = 1
                                              self._connected = True
                                              return True
                                          except Exception as e:
                                              self.logger.error("Xiaomi_Robvac: Error {0}, Cycle {1} ".format(e,self.retry_count))
                                              self.retry_count = self.retry_count+1
                                              self._connected = False
                                              return False
                                          #finally:
                                              
                                  
                          # ----------------------------------------------------------------------------------------------
                          # Daten Lesen, über SHNG bei item_Change
                          # ----------------------------------------------------------------------------------------------
                          def groupread(self, ga, dpt):
                              pass
                              
                          # ----------------------------------------------------------------------------------------------
                          # Daten Lesen, zyklisch
                          # ----------------------------------------------------------------------------------------------    
                      
                          
                          def _read(self):
                              data = {}
                              #config
                              self._connect()
                      
                              try:
                                  clean_history = self.vakuum.clean_history()
                                  self._data['clean_total_count'] =     int(clean_history.count)
                                  self._data['clean_total_area'] =      round(clean_history.total_area,0)
                                  self._data['clean_total_duration'] =  clean_history.total_duration.total_seconds() // 3600
                                  #self._data['clean_total_duration'] =  clean_history.total_duration.seconds // 3600
                                  self._data['clean_ids'] =             clean_history.ids
                                  self.logger.debug("Xiaomi_Robvac: Reingungsstatistik Anzahl {0}, Fläche {1}², Dauer {2}, clean ids {3}".format(
                                                                                                                          self._data['clean_total_count'],
                                                                                                                          self._data['clean_total_area'],
                                                                                                                          self._data['clean_total_duration'],
                                                                                                                          self._data['clean_ids']))
                      
                                  #letzte reinigung
                                  #funktioniert nur mit übergebener id
                                  if self._data['clean_ids'] != None:
                                      #self._data['clean_ids'] = self._data['clean_ids'].sort(reverse=True)
                                      self._data['clean_details_last0'] = self.vakuum.clean_details(self._data['clean_ids'][0],return_list=True)
                                      self._data['last0_area'] =          round(self._data['clean_details_last0'][0].area,2)
                                      self._data['last0_complete'] =      self._data['clean_details_last0'][0].complete
                                      self._data['last0_duration'] =      self._data['clean_details_last0'][0].duration.total_seconds()
                                      self._data['last0_start_date'] =    self._data['clean_details_last0'][0].start.strftime("%d.%m.%Y")
                                      self._data['last0_start_time'] =    self._data['clean_details_last0'][0].start.strftime("%H:%I")
                                      self._data['last0_end_date'] =      self._data['clean_details_last0'][0].start.strftime("%d.%m.%Y")
                                      self._data['last0_end_time'] =      self._data['clean_details_last0'][0].start.strftime("%H:%I")
                                      self._data['clean_details_last1'] = self.vakuum.clean_details(self._data['clean_ids'][1],return_list=True)
                                      self._data['last1_area'] =          round(self._data['clean_details_last1'][0].area,2)
                                      self._data['last1_complete'] =      self._data['clean_details_last1'][0].complete
                                      self._data['last1_duration'] =      self._data['clean_details_last1'][0].duration.total_seconds()
                                      self._data['last1_start_date'] =    self._data['clean_details_last1'][0].start.strftime("%d.%m.%Y")
                                      self._data['last1_start_time'] =    self._data['clean_details_last1'][0].start.strftime("%H:%I")
                                      self._data['last1_end_date'] =      self._data['clean_details_last1'][0].start.strftime("%d.%m.%Y")
                                      self._data['last1_end_time'] =      self._data['clean_details_last1'][0].start.strftime("%H:%I")
                                      self._data['clean_details_last2'] = self.vakuum.clean_details(self._data['clean_ids'][2],return_list=True)
                                      self._data['last2_area'] =          round(self._data['clean_details_last2'][0].area,2)
                                      self._data['last2_complete'] =      self._data['clean_details_last2'][0].complete
                                      self._data['last2_duration'] =      self._data['clean_details_last2'][0].duration.total_seconds()
                                      self._data['last2_start_date'] =    self._data['clean_details_last2'][0].start.strftime("%d.%m.%Y")
                                      self._data['last2_start_time'] =    self._data['clean_details_last2'][0].start.strftime("%H:%I")
                                      self._data['last2_end_date'] =      self._data['clean_details_last2'][0].start.strftime("%d.%m.%Y")
                                      self._data['last2_end_time'] =      self._data['clean_details_last2'][0].start.strftime("%H:%I")
                                      self._data['clean_details_last3'] = self.vakuum.clean_details(self._data['clean_ids'][3],return_list=True)
                                      self._data['last3_area'] =          round(self._data['clean_details_last3'][0].area,2)
                                      self._data['last3_complete'] =      self._data['clean_details_last3'][0].complete
                                      self._data['last3_duration'] =      self._data['clean_details_last3'][0].duration.total_seconds()
                                      self._data['last3_start_date'] =    self._data['clean_details_last3'][0].start.strftime("%d.%m.%Y")
                                      self._data['last3_start_time'] =    self._data['clean_details_last3'][0].start.strftime("%H:%I")
                                      self._data['last3_end_date'] =      self._data['clean_details_last3'][0].start.strftime("%d.%m.%Y")
                                      self._data['last3_end_time'] =      self._data['clean_details_last3'][0].start.strftime("%H:%I")
                                      self.logger.debug("Xiaomi_Robvac: Historische id0 {}, id1{}, id2 {}, id3 {}".format(self._data['clean_details_last0'],
                                                                                                                  self._data['clean_details_last1'],
                                                                                                                  self._data['clean_details_last2'],
                                                                                                                  self._data['clean_details_last3']))
                                      
                                  carpet_mode = self.vakuum.carpet_mode()
                                  self._data['carpetmode_high'] =       carpet_mode.current_high
                                  self._data['carpetmode_integral'] =  carpet_mode.current_integral
                                  self._data['carpetmode_low'] =        carpet_mode.current_low
                                  self._data['carpetmode_enabled'] =    carpet_mode.enabled
                                  self._data['carpetmode_stall_time'] = carpet_mode.stall_time
                                  self.logger.debug("Xiaomi_Robvac: Carpet Mode high: {}, integral: {}, low: {}, enabled: {}, , stall_time: {}".format(self._data['carpetmode_high'],
                                                                                                                          self._data['carpetmode_integral'],
                                                                                                                          self._data['carpetmode_low'],
                                                                                                                          self._data['carpetmode_enabled'],
                                                                                                                          self._data['carpetmode_stall_time']))
                                
                                  #status
                                  self._data['serial'] =    self.vakuum.serial_number()
                                  self._data['vol'] =       self.vakuum.sound_volume()
                                  self._data['dnd_status'] = self.vakuum.dnd_status().enabled
                                  self._data['dnd_start'] = self.vakuum.dnd_status().start
                                  self._data['dnd_end'] =   self.vakuum.dnd_status().end
                                  self.logger.debug("Xiaomi_Robvac: Serial{}, vol {}, dnd status {}, dnd start {},dnd end {},".format(self._data['serial'],
                                                                                                                          self._data['vol'],
                                                                                                                          self._data['dnd_status'],
                                                                                                                          self._data['dnd_start'],
                                                                                                                          self._data['dnd_end']))
                                  
                                  self._data['device_group'] = self.vakuum.get_device_group()
                                  self._data['segment_status'] = self.vakuum.get_segment_status()
                                  if self._data['segment_status'] == None:
                                      self._data['segment_status'] = False
                                  self._data['fanspeed'] =  self.vakuum.status().fanspeed
                                  self._data['batt'] =      self.vakuum.status().battery
                                  self._data['area'] =      round(self.vakuum.status().clean_area,2)
                                  self._data['cleantime'] = self.vakuum.status().clean_time.total_seconds() // 3600
                                  self._data['aktiv'] =     self.vakuum.status().is_on #reinigt?
                                  self._data['zone_cleaning'] = self.vakuum.status().in_zone_cleaning #reinigt?
                                  self._data['is_error'] = self.vakuum.status().got_error
                                  self.logger.debug("Xiaomi_Robvac: segment_status, fanspeed {},batt {}, area {}, cleantime {}, aktiv {} zonen_reinigung {} , device group{}".format(self._data['segment_status'], self._data['fanspeed'],
                                                                                                                          self._data['batt'],
                                                                                                                          self._data['area'],
                                                                                                                          self._data['cleantime'],
                                                                                                                          self._data['aktiv'],
                                                                                                                          self._data['zone_cleaning'],
                                                                                                                          self._data['device_group']))
                                  self._data['error'] =     self.vakuum.status().error_code
                                  self._data['pause'] =     self.vakuum.status().is_paused #reinigt?
                                  self._data['status'] =    self.vakuum.status().state #status charging
                                  self._data['timer'] =     self.vakuum.timer()#[self.vakuum.timer()[0]['id'], self.vakuum.timer()[0]['action'], self.vakuum.timer()[0]['enabled'], self.vakuum.timer()[0]['ts']]
                                  self._data['timezone'] =  self.vakuum.timezone()
                                
                                  #bekannet States: Charging, Pause, Charging Disconnected
                                  if self._data['status'] == 'Charging':
                                      self._data['charging'] = True
                                  else:
                                      self._data['charging'] = False
                      
                                  #->2018-12-26  11:10:37 DEBUG    plugins.xiaomi_vac Xiaomi_Robvac: Lese batt 100 area0.0 time 0:00:15 status False stateCharging
                                  self.logger.debug("Xiaomi_Robvac: error {}, pause {}, status{} , timer {}, timezone{}".format(   self._data['error'],
                                                                                                                             self._data['pause'],
                                                                                                                             self._data['status'],
                                                                                                                             self._data['timer'],
                                                                                                                             self._data['timezone']))
                                  #buerste
                                  #consumable_status()
                                  self._data['sensor_dirty'] =      self.vakuum.consumable_status().sensor_dirty.total_seconds() // 3600
                                  self._data['sensor_dirty_left'] = self.vakuum.consumable_status().sensor_dirty_left.total_seconds() // 3600
                                  self._data['side_brush'] =        self.vakuum.consumable_status().side_brush.total_seconds() // 3600
                                  self._data['side_brush_left'] =   self.vakuum.consumable_status().side_brush_left.total_seconds() // 3600
                                  self._data['main_brush'] =        self.vakuum.consumable_status().main_brush.total_seconds() // 3600
                                  self._data['main_brush_left'] =   self.vakuum.consumable_status().main_brush_left.total_seconds() // 3600
                                  self._data['filter'] =            self.vakuum.consumable_status().filter.total_seconds() // 3600
                                  self._data['filter_left'] =       self.vakuum.consumable_status().filter_left.total_seconds() // 3600
                                  self.logger.debug("Xiaomi_Robvac: buerste seite {0}/{1} Buerste Haupt {2}/{3} filter{4}/{5}".format(self._data['side_brush'],
                                                                                                                                      self._data['side_brush_left'],
                                                                                                                                      self._data['main_brush'],
                                                                                                                                      self._data['main_brush_left'],
                                                                                                                                      self._data['filter'],
                                                                                                                                      self._data['filter_left']))
                                  self.logger.debug("Xiaomi_Robvac:{}".format(self._data))
                              except Exception as e:
                                      self.logger.error("Xiaomi_Robvac: Error {}".format(e))
                                      self._connected = False
                              
                      
                              for x in self._data:
                                  if x in self.messages:
                                      self.logger.debug("Xiaomi_Robvac: Update item {1} mit key {0} = {2}".format(x, self.messages[x], self._data[x]))
                                      item = self.messages[x]
                                      item(self._data[x], 'Xiaomi Robovac')
                      
                      
                          # ----------------------------------------------------------------------------------------------
                          # Befehl senden, wird aufgerufen wenn sich item  mit robvac ändert!
                          # ----------------------------------------------------------------------------------------------
                          def update_item(self, item, caller=None, source=None, dest=None):
                              if caller != 'Robvac':
                                  #if 'robvac' in item.conf:
                                  #    message = item.conf['robvac']
                                  if self.has_iattr(item.conf, 'robvac'):
                                      #bei boolischem item Item zurücksetzen, damit enforce_updates nicht nötig!
                                      if item() == True:
                                          item(False, 'Robvac')
                       
                                      message = self.get_iattr_value(item.conf, 'robvac')
                                      self.logger.debug("Xiaomi_Robvac: Tu dies und das !{0} , weil item {1} geändert wurde   ".format(message, item))
                                      
                                      if message == 'fanspeed':
                                          self.vakuum.set_fan_speed(item())
                                          self.logger.debug("Xiaomi_Robvac: Hab {0} geaendert wurde                       ".format(self.vakuum.fan_speed()))
                                      elif message == 'vol':
                                          if item() > 100:
                                              vol = 100
                                          else:
                                              vol = item()
                                          self.vakuum.set_sound_volume(vol)
                                      elif message == 'set_start':
                                          self.vakuum.start()
                                      elif message == 'set_stop':
                                          self.vakuum.pause()
                                      elif message == "set_home":
                                          self.vakuum.home()
                                      elif message == "set_pause":
                                          self.vakuum.pause()
                                      elif message == "set_spot":
                                          self.vakuum.spot()
                                      elif message == "set_find":
                                          self.vakuum.find()
                                      elif message == "reset_filtertimer":
                                          self.vakuum.reset_consumable()
                                      elif message == "disable_dnd":
                                          self.vakuum.disable_dnd()
                                          
                                      elif message == "set_dnd":
                                      #start_hr, start_min, end_hr, end_min
                                          self.vakuum.set_dnd(item()[0], item()[1],item()[2], item()[3])
                                      elif message == "clean_zone":
                                      #Clean zones. :param List zones: List of zones to clean: [[x1,y1,x2,y2, iterations],[x1,y1,x2,y2, iterations]]
                                          self.vakuum.zoned_clean(item()[0], item()[1],item()[2], item()[3], item()[4])
                                      elif message == "go_to":    
                                          self.vakuum.goto(item()[0], item()[1])
                                      elif message == "create_nogo_zones":
                                          self.vakuum.create_nogo_zone(item()[0], item()[1])
                       
                                          pass
                                          
                          def run(self):
                              self.alive = True
                              self.logger.debug("Xiaomi_Robvac: Found items{}".format(self.messages))
                              
                          def stop(self):
                              self.alive = False
                              
                          def parse_item(self, item):
                              if self.has_iattr(item.conf, 'robvac'):
                                  message = self.get_iattr_value(item.conf, 'robvac')
                                  self.logger.debug("Xiaomi_Robvac: {0} keyword {1}".format(item, message))
                      
                                  if not message in self.messages:
                                      self.messages[message] = item
                                      
                                  return self.update_item
                      
                          def update_item_read(self, item, caller=None, source=None, dest=None):
                              if self.has_iattr(item.conf, 'robvac'):
                                  for message in item.get_iattr_value(item.conf, 'robvac'):
                                  #for message in item.conf['robvac']:  # send status update
                                      self.logger.debug("Xiaomi_Robvac: update_item_read {0}".format(message))
                      # ------------------------------------------
                      #    Webinterface Methoden
                      # ------------------------------------------  
                      
                          def get_connection_info(self):
                              info = {}
                              info['ip'] = self._ip
                              info['token'] = self._token
                              info['cycle'] = self._cycle
                              info['connected'] = self._connected
                              return info
                              
                          def init_webinterface(self):
                              """"
                              Initialize the web interface for this plugin
                      
                              This method is only needed if the plugin is implementing a web interface
                              """
                              try:
                                  self.mod_http = Modules.get_instance().get_module(
                                      'http')  # try/except to handle running in a core version that does not support modules
                              except:
                                  self.mod_http = None
                              if self.mod_http == None:
                                  self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname()))
                                  return False
                      
                              # set application configuration for cherrypy
                              webif_dir = self.path_join(self.get_plugin_dir(), 'webif')
                              config = {
                                  '/': {
                                      'tools.staticdir.root': webif_dir,
                                  },
                                  '/static': {
                                      'tools.staticdir.on': True,
                                      'tools.staticdir.dir': 'static'
                                  }
                              }
                              
                              self.logger.debug("Plugin '{0}': {1}, {2}, {3}, {4}, {5}".format(self.get_shortname(), webif_dir, self.get_shortname(),config,  self.get_classname(), self.get_instance_name()))
                              # Register the web interface as a cherrypy app
                              self.mod_http.register_webif(WebInterface(webif_dir, self),
                                                           self.get_shortname(),
                                                           config,
                                                           self.get_classname(), self.get_instance_name(),
                                                           description='')
                      
                              return True
                      
                      
                      # ------------------------------------------
                      #    Webinterface of the plugin
                      # ------------------------------------------
                      
                      import cherrypy
                      from jinja2 import Environment, FileSystemLoader
                      
                      class WebInterface(SmartPluginWebIf):
                      
                      
                          def __init__(self, webif_dir, plugin):
                              """
                              Initialization of instance of class WebInterface
                      
                              :param webif_dir: directory where the webinterface of the plugin resides
                              :param plugin: instance of the plugin
                              :type webif_dir: str
                              :type plugin: object
                              """
                              self.logger = logging.getLogger(__name__)
                              self.webif_dir = webif_dir
                              self.plugin = plugin
                              self.tplenv = self.init_template_environment()
                              self.logger.debug("Plugin : Init Webif")
                              self.items = Items.get_instance()
                              
                          @cherrypy.expose
                          def index(self, reload=None):
                              """
                              Build index.html for cherrypy
                              Render the template and return the html file to be delivered to the browser
                              :return: contents of the template after beeing rendered
                              """
                              plgitems = []
                              for item in self.items.return_items():
                                  if ('robvac' in item.conf):
                                      plgitems.append(item)
                              self.logger.debug("Plugin : Render index Webif")
                              tmpl = self.tplenv.get_template('index.html')
                              return tmpl.render(plugin_shortname=self.plugin.get_shortname(),
                                                  plugin_version=self.plugin.get_version(),
                                                  plugin_info=self.plugin.get_info(),
                                                  p=self.plugin,
                                                  connection = self.plugin.get_connection_info(),
                                                  webif_dir = self.webif_dir ,
                                                  items=sorted(plgitems, key=lambda k: str.lower(k['_path'])))

                      der html dazu sieht wie folgt bei mir aus:
                      HTML-Code:
                      /**
                      * -----------------------------------------------------------------------------
                      * @package     smartVISU
                      * @author      Martin Gleiß
                      * @copyright   2012 - 2015
                      * @license     GPL [http://www.gnu.de]
                      * -----------------------------------------------------------------------------
                      */
                      
                      
                      {% extends "rooms.html" %}
                      {% import "eigen.html" as eigen %}
                      {% import "icon.html" as icon %}
                      
                      {% block content %}
                          
                          <h1><img class="icon icon0" src='{{ icon0 }}scene_robo_vac_cleaner.svg'/>Staubsaugroboter</h1>
                      
                      <div class="center">
                          <div class="set-2" data-role="collapsible-set" data-theme="c" data-content-theme="a" data-mini="true">
                              <div data-role="collapsible" data-collapsed="false">
                                  
                                  <h3>Status Staubsaugroboter</h3>
                                  
                                  <div align="left">
                                      <b>Zustand: </b></br>
                                      Batterie: {{ icon.battery('battery_state', '', 'xiaomi_roborock.live.batterie_status', '0', '100') }}  {{ basic.value('batt', 'xiaomi_roborock.live.batterie_status') }}%&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;
                                      Lüfter:   {{ icon.volume('luefterspeed', '', 'xiaomi_roborock.einstellungen.luefter_speed', '0', '100') }}
                                      </br>
                                      {% if xiaomi_roborock.live.reinigt == 1 %}
                                          <hr>
                                          <b>Saugroboter reinigt:</b></br>
                                          Fläche gereinigt: {{ basic.value('qmlive', 'xiaomi_roborock.live.flaeche', 'qm') }} |
                                          Reinigt schon: {{ basic.value('timelive', 'xiaomi_roborock.live.reinigungszeit', 'h') }} |
                                          Lüftergeschwindigkeit: {{ basic.value('luefterspeed1', 'xiaomi_roborock.einstellungen.luefter_speed') }}% |
                                          {{ robvac.carpet('carpetmode', 'xiaomi_roborock.live.carpetmode_enabled', 'xiaomi_roborock.live.carpetmode_low', 'xiaomi_roborock.live.carpetmode_integral', 'xiaomi_roborock.live.carpetmode_high') }}
                                      {% elseif xiaomi_roborock.live.errorcode != '' %}
                                          {{ basic.text('err', 'xiaomi_roborock.live.errorcode', 'xiaomi_roborock.live.errorcode', '') }}
                                      {% elseif xiaomi_roborock.live.dnd_status == 1 %}
                                          DND Modus aktiv
                                      {% elseif ('Charging' in xiaomi_roborock.live.zustand) == True %}
                                          Saugroboter ist in der Ladestation
                                      {% elseif ('Pause' in xiaomi_roborock.live.zustand) == True %}
                                          Reinigung pausiert ???
                                      {% elseif ('Charger disconnected' in xiaomi_roborock.live.zustand) == True %}
                                          Saugroboter steht irgendwo?
                                      {% endif %}
                                  </div>
                                  
                                  <hr>
                                  
                                  <div >
                                      <div style="float:right; background-image:url(pages/Puff/pics/xiaomi_logo.png); opacity: 1.0; border-radius: 4px; z-index: 0; width: 180px; height: 150px;">
                                      
                                      </div>
                                      <div align="left">
                                          <b>Steuerung:</b>
                                          <span data-role="controlgroup" data-type="horizontal">
                                              {{ basic.dual('start',  'xiaomi_roborock.befehl.start',        'audio_play.svg',  'audio_play.svg') }}
                                              {{ basic.dual('stop',   'xiaomi_roborock.befehl.stop',         'audio_stop.svg',  'audio_stop.svg') }}
                                              {{ basic.dual('pause',  'xiaomi_roborock.befehl.pause',        'audio_pause.svg', 'audio_pause.svg') }}
                                          </span>
                                              {{ basic.button('home', 'xiaomi_roborock.befehl.basis',        '',                'home',            '1', 'mini') }}
                                              {{ basic.button('zone', 'xiaomi_roborock.befehl.spot_cleaner', 'Zone',            '',                '1', 'mini') }}
                                              {{ basic.button('find', 'xiaomi_roborock.befehl.find',         '? find ?',        '',                '1', 'mini') }}
                                          
                                          <hr>
                                          
                                          <b>Gesamt:</b></br>
                                          Fläche: {{ basic.value('qm', 'xiaomi_roborock.statistik.gereinigte_flaeche', 'm²') }}&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;
                                          Anzahl Reinigungen: {{ basic.value('anzsahl', 'xiaomi_roborock.statistik.anzahl_reinigungen') }}&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;
                                          Laufzeit: {{ basic.value('reinigungszeit', 'xiaomi_roborock.statistik.gesamtlaufzeit', 'h0')}}</br>
                                          </br>
                                          <b>Zeit Verbleibend:</b></br>
                                          Bürste Seite: {{ basic.value('b_side', 'xiaomi_roborock.stundenzaehler.buerste_seite_verbleibend', 'h0') }}&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;
                                          Hauptbürste: {{ basic.value('b_haupt', 'xiaomi_roborock.stundenzaehler.buerste_haupt_verbleibend', 'h0') }}&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;
                                          Filter: {{ basic.value('filterzeit', 'xiaomi_roborock.stundenzaehler.filter_verbleibend', 'h0') }}&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;
                                          Sensor: {{ basic.value('sensorzeit', 'xiaomi_roborock.stundenzaehler.sensor_reinigen_verbleibend', 'h0') }}</br>
                                      </div>
                      
                                  </div>
                      
                              </div>
                          </div>
                      </div>
                      
                      {% endblock %}
                      Hier funktioniert die Fallunterscheidung beim Zustand des Roboters nicht richtig. Ohne die Klammern und die True-Abfrage funktioniert aber gar nichts bei mir.

                      Kommentar


                        #71
                        Cool, dass sich noch wer um das Plugin kümmert. Ich habe derzeit leider gar keine Zeit dafür
                        Vielleicht dann nach den Anpassungen mal der Pull Request, Bonze ? https://github.com/smarthomeNG/plugins/pulls

                        Kommentar


                          #72
                          Hallo,

                          Gue0411 verwendet ja eine ältere python-miio version. Kann es sein, dass sich hier die Syntax geändert hat?
                          Dann müsste das Plugin ja die python-miio Version abfragen und je nach Version einen unterschiedlichen Aufruf durchführen?

                          Und ja, ein PR wäre sinnvoll. Ein neues Release der Plugins wird ja gerade vorbereitet.

                          Gruß,
                          Hendrik

                          Kommentar


                            #73
                            so, habe auch nochmal geschaut, mit der Reingungszeit und des Reingungsstatuses gibt es probleme, sodass dieser selbsständig wider auf False gesetzt wird, das komische ist aber, das dies nicht im Log durch das Plugin geschieht! Die Werte werden auf jedenfall richtig gelesen und geschrieben..

                            Kommentar


                              #74
                              Mir ist nicht ganz klar wie ich diese Meldungen los werde, sie kommen wohl vom Modul, nicht Plugin:
                              Code:
                               
                               WARNING  miio.vacuum       This method will be returning the details without wrapping them into a list in the near future. The current behavior can be kept by passing return_list=True and this warning will be removed when the default gets changed.

                              Kommentar


                                #75
                                Onkelandy, ja der Fehler kommt vom Modul

                                hab den Fehler denke ich mit dem Rücksetzen gefunden...
                                und noch die Start/End Time korrigiert

                                jetzt ist nurnoch ein Fehler drin, das er bei der Reinigungsduaer, nicht richtig rechnet..

                                Gue0411 , welche änderungen hast du noch vorgenommen, die eich noch einspielen muss?

                                Code:
                                #
                                #!/usr/bin/env python3
                                # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab
                                #
                                ####################################################################################
                                ######################################################################################
                                #
                                #  Copyright 2018 Version-1    Manuel Holländer
                                #  Copyright 2019 Version-2    Manuel Holländer
                                ####################################################################################
                                #
                                #  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.
                                #
                                #  smarthomeNG 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/>.
                                #
                                ####################################################################################
                                #
                                #   VERSION - 2
                                #
                                ####################################################################################
                                #
                                import logging
                                import threading
                                import struct
                                import binascii
                                import re
                                import time
                                from datetime import datetime, timedelta
                                
                                import miio
                                from miio.vacuum import Vacuum, VacuumException
                                from miio.vacuumcontainers import (VacuumStatus, ConsumableStatus, DNDStatus, CleaningDetails, CleaningSummary, Timer)
                                from miio.discovery import Discovery
                                
                                from lib.model.smartplugin import *
                                from lib.module import Modules
                                from lib.item import Items
                                
                                class Robvac(SmartPlugin):
                                    ALLOW_MULTIINSTANCE = False
                                    PLUGIN_VERSION="0.4.0"
                                    
                                    def __init__(self, smarthome,ip='127.0.0.1', token='', read_cycle=20):
                                        self._ip = str(ip)
                                        self._token = str(token)
                                        self._cycle = int(read_cycle)
                                        self._sh = smarthome
                                        self.logger = logging.getLogger(__name__)
                                        
                                        self.messages = {}
                                        self.found = False
                                        self._lock = threading.Lock()
                                        self.retry_count_max = 3
                                        self.retry_count = 1
                                        self._connected = False
                                        self._data = {}
                                        if not self.init_webinterface():
                                            self._init_complete = False
                                            
                                        if self._token == '':
                                            self.logger.error("Xiaomi_Robvac: No Key for Communication given, Plugin would not start!")
                                            pass
                                        else:
                                            self.logger.debug("Xiaomi_Robvac: Plugin Start!")
                                            if self._cycle > 10:
                                                self._sh.scheduler.add('Xiaomi_Robvac Read cycle', self._read, prio=5, cycle=self._cycle)
                                            else:
                                                self.logger.warning("Xiaomi_Robvac: Read Cycle is to fast! < 10s, not starting!")
                                    # ----------------------------------------------------------------------------------------------
                                    # Verbinden zum Roboter
                                    # ----------------------------------------------------------------------------------------------
                                    def _connect(self):        
                                            if self._connected == False:
                                                for i in range(0,self.retry_count_max-self.retry_count):
                                                    try:
                                                        self.vakuum = miio.Vacuum(self._ip,self._token, 0, 0)
                                                        self.retry_count = 1
                                                        self._connected = True
                                                        return True
                                                    except Exception as e:
                                                        self.logger.error("Xiaomi_Robvac: Error {0}, Cycle {1} ".format(e,self.retry_count))
                                                        self.retry_count = self.retry_count+1
                                                        self._connected = False
                                                        return False
                                                    #finally:
                                                        
                                            
                                    # ----------------------------------------------------------------------------------------------
                                    # Daten Lesen, über SHNG bei item_Change
                                    # ----------------------------------------------------------------------------------------------
                                    def groupread(self, ga, dpt):
                                        pass
                                        
                                    # ----------------------------------------------------------------------------------------------
                                    # Daten Lesen, zyklisch
                                    # ----------------------------------------------------------------------------------------------     
                                
                                    
                                    def _read(self):
                                        data = {}
                                        #config
                                        self._connect()
                                
                                        try:
                                            clean_history = self.vakuum.clean_history()
                                            self._data['clean_total_count'] =     int(clean_history.count)
                                            self._data['clean_total_area'] =      round(clean_history.total_area,2)
                                            self._data['clean_total_duration'] =  clean_history.total_duration.total_seconds() // 3600
                                            self._data['clean_ids'] =             clean_history.ids
                                            self.logger.debug("Xiaomi_Robvac: Reingungsstatistik Anzahl {0}, Fläche {1}², Dauer {2}, clean ids {3}".format(
                                                                                                                                    self._data['clean_total_count'],
                                                                                                                                    self._data['clean_total_area'],
                                                                                                                                    self._data['clean_total_duration'],
                                                                                                                                    self._data['clean_ids']))
                                
                                            #letzte reinigung
                                            #funktioniert nur mit übergebener id
                                            if self._data['clean_ids'] != None:
                                                #self._data['clean_ids'] = self._data['clean_ids'].sort(reverse=True)
                                                self._data['clean_details_last'] = self.vakuum.clean_details(self._data['clean_ids'][1],return_list=True)
                                                self._data['last1_area'] =          round(self._data['clean_details_last'][0].area,2)
                                                self._data['last1_complete'] =      self._data['clean_details_last'][0].complete
                                                self._data['last1_duration'] =      round(self._data['clean_details_last'][0].duration.total_seconds()/ 3600,2)
                                                self._data['last1_start_date'] =    self._data['clean_details_last'][0].start.strftime("%d.%m.%Y")
                                                self._data['last1_start_time'] =    self._data['clean_details_last'][0].start.strftime("%H:%M")                 
                                                self._data['last1_end_date'] =      self._data['clean_details_last'][0].start.strftime("%d.%m.%Y")
                                                self._data['last1_end_time'] =      (self._data['clean_details_last'][0].start+self._data['clean_details_last'][0].duration).strftime("%H:%M")
                                                
                                                self._data['clean_details_last1'] = self.vakuum.clean_details(self._data['clean_ids'][2],return_list=True)
                                                self._data['last2_area'] =          round(self._data['clean_details_last1'][0].area,2)
                                                self._data['last2_complete'] =      self._data['clean_details_last1'][0].complete
                                                self._data['last2_duration'] =      round(self._data['clean_details_last1'][0].duration.total_seconds()/ 3600,2)
                                                self._data['last2_start_date'] =    self._data['clean_details_last1'][0].start.strftime("%d.%m.%Y")
                                                self._data['last2_start_time'] =    self._data['clean_details_last1'][0].start.strftime("%H:%M")   
                                                self._data['last2_end_date'] =      self._data['clean_details_last1'][0].start.strftime("%d.%m.%Y")
                                                self._data['last2_end_time'] =      (self._data['clean_details_last1'][0].start+self._data['clean_details_last1'][0].duration).strftime("%H:%M")
                                                
                                                self._data['clean_details_last2'] = self.vakuum.clean_details(self._data['clean_ids'][3],return_list=True)
                                                self._data['last3_area'] =          round(self._data['clean_details_last2'][0].area,2)
                                                self._data['last3_complete'] =      self._data['clean_details_last2'][0].complete
                                                self._data['last3_duration'] =      round(self._data['clean_details_last2'][0].duration.total_seconds()/ 3600,2)
                                                self._data['last3_start_date'] =    self._data['clean_details_last2'][0].start.strftime("%d.%m.%Y")
                                                self._data['last3_start_time'] =    self._data['clean_details_last2'][0].start.strftime("%H:%M")   
                                                self._data['last3_end_date'] =      self._data['clean_details_last2'][0].start.strftime("%d.%m.%Y")
                                                self._data['last3_end_time'] =      (self._data['clean_details_last2'][0].start+self._data['clean_details_last2'][0].duration).strftime("%H:%M")
                                                
                                                self.logger.debug("Xiaomi_Robvac: Historische id1 {}, id2{}, id3 {}".format(self._data['clean_details_last'],
                                                                                                                            self._data['clean_details_last1'],
                                                                                                                            self._data['clean_details_last2']))
                                                                                                                            
                                                self.logger.debug("Xiaomi_Robvac: Clean Run complete id1 {}, id2{}, id3 {}".format(self._data['last1_complete'],
                                                                                                                            self._data['last2_complete'],
                                                                                                                            self._data['last3_complete'],))
                                            carpet_mode = self.vakuum.carpet_mode()
                                            self._data['carpetmode_high'] =       carpet_mode.current_high
                                            self._data['carpetmode_integral'] =  carpet_mode.current_integral
                                            self._data['carpetmode_low'] =        carpet_mode.current_low
                                            self._data['carpetmode_enabled'] =    carpet_mode.enabled
                                            self._data['carpetmode_stall_time'] = carpet_mode.stall_time
                                            self.logger.debug("Xiaomi_Robvac: Carpet Mode high: {}, integral: {}, low: {}, enabled: {}, , stall_time: {}".format(self._data['carpetmode_high'],
                                                                                                                                    self._data['carpetmode_integral'],
                                                                                                                                    self._data['carpetmode_low'],
                                                                                                                                    self._data['carpetmode_enabled'],
                                                                                                                                    self._data['carpetmode_stall_time']))
                                           
                                            #status
                                            self._data['serial'] =    self.vakuum.serial_number()
                                            self._data['vol'] =       self.vakuum.sound_volume()
                                            self._data['dnd_status'] = self.vakuum.dnd_status().enabled
                                            self._data['dnd_start'] = self.vakuum.dnd_status().start
                                            self._data['dnd_end'] =   self.vakuum.dnd_status().end
                                            self.logger.debug("Xiaomi_Robvac: Serial{}, vol {}, dnd status {}, dnd start {},dnd end {},".format(self._data['serial'],
                                                                                                                                    self._data['vol'],
                                                                                                                                    self._data['dnd_status'],
                                                                                                                                    self._data['dnd_start'],
                                                                                                                                    self._data['dnd_end']))
                                            
                                            self._data['device_group'] = self.vakuum.get_device_group()
                                            self._data['segment_status'] = self.vakuum.get_segment_status()
                                            self._data['fanspeed'] =  self.vakuum.status().fanspeed
                                            self._data['batt'] =      self.vakuum.status().battery
                                            self._data['area'] =      round(self.vakuum.status().clean_area,2)
                                            self._data['cleantime'] = self.vakuum.status().total_seconds() // 3600
                                            self._data['aktiv'] =     self.vakuum.status().is_on #reinigt?
                                            self._data['zone_cleaning'] = self.vakuum.status().in_zone_cleaning #reinigt?
                                            self._data['is_error'] = self.vakuum.status().got_error
                                            self.logger.debug("Xiaomi_Robvac: segment_status, fanspeed {},batt {}, area {}, cleantime {}, aktiv {} zonen_reinigung {} , device group{}".format(self._data['segment_status'], self._data['fanspeed'],
                                                                                                                                    self._data['batt'],
                                                                                                                                    self._data['area'],
                                                                                                                                    self._data['cleantime'],
                                                                                                                                    self._data['aktiv'],
                                                                                                                                    self._data['zone_cleaning'],
                                                                                                                                    self._data['device_group']))
                                            self._data['error'] =     self.vakuum.status().error_code
                                            self._data['pause'] =     self.vakuum.status().is_paused #reinigt?
                                            self._data['status'] =    self.vakuum.status().state #status charging
                                            self._data['timer'] =     self.vakuum.timer()#[self.vakuum.timer()[0]['id'], self.vakuum.timer()[0]['action'], self.vakuum.timer()[0]['enabled'], self.vakuum.timer()[0]['ts']]
                                            self._data['timezone'] =  self.vakuum.timezone()
                                           
                                            #bekannet States: Charging, Pause, Charging Disconnected
                                            if self._data['status'] == 'Charging':
                                                self._data['charging'] = True
                                            else:
                                                self._data['charging'] = False
                                
                                            #->2018-12-26  11:10:37 DEBUG    plugins.xiaomi_vac Xiaomi_Robvac: Lese batt 100 area0.0 time 0:00:15 status False stateCharging
                                            self.logger.debug("Xiaomi_Robvac: error {}, pause {}, status{} , timer {}, timezone{}".format(   self._data['error'],
                                                                                                                                       self._data['pause'],
                                                                                                                                       self._data['status'],
                                                                                                                                       self._data['timer'],
                                                                                                                                       self._data['timezone']))
                                            #buerste
                                            #consumable_status()
                                            self._data['sensor_dirty'] =      self.vakuum.consumable_status().sensor_dirty.total_seconds() // 3600
                                            self._data['sensor_dirty_left'] = self.vakuum.consumable_status().sensor_dirty_left.total_seconds()// 3600
                                            self._data['side_brush'] =        self.vakuum.consumable_status().side_brush.total_seconds() // 3600
                                            self._data['side_brush_left'] =   self.vakuum.consumable_status().side_brush_left.total_seconds() // 3600
                                            self._data['main_brush'] =        self.vakuum.consumable_status().main_brush.total_seconds() // 3600
                                            self._data['main_brush_left'] =   self.vakuum.consumable_status().main_brush_left.total_seconds() // 3600
                                            self._data['filter'] =            self.vakuum.consumable_status().filter.total_seconds() // 3600
                                            self._data['filter_left'] =       self.vakuum.consumable_status().filter_left.total_seconds() // 3600
                                            self.logger.debug("Xiaomi_Robvac: buerste seite {0}/{1} Buerste Haupt {2}/{3} filter{4}/{5}".format(self._data['side_brush'],
                                                                                                                                                self._data['side_brush_left'],
                                                                                                                                                self._data['main_brush'],
                                                                                                                                                self._data['main_brush_left'],
                                                                                                                                                self._data['filter'],
                                                                                                                                                self._data['filter_left']))
                                            self.logger.debug("Xiaomi_Robvac:{}".format(self._data))
                                        except Exception as e:
                                                self.logger.error("Xiaomi_Robvac: Error {}".format(e))
                                                self._connected = False
                                        
                                
                                        for x in self._data:
                                            if x in self.messages:
                                                self.logger.debug("Xiaomi_Robvac: Update item {1} mit key {0} = Wert {2}".format(x, self.messages[x], self._data[x]))
                                                item = self.messages[x]
                                                item(self._data[x], 'Xiaomi Robovac')
                                
                                
                                    # ----------------------------------------------------------------------------------------------
                                    # Befehl senden, wird aufgerufen wenn sich item  mit robvac ändert!
                                    # ----------------------------------------------------------------------------------------------
                                    def update_item(self, item, caller=None, source=None, dest=None):
                                        if caller != 'Robvac':
                                            #if 'robvac' in item.conf:
                                            #    message = item.conf['robvac']
                                            if self.has_iattr(item.conf, 'robvac'):
                                                #bei boolischem item Item zurücksetzen, damit enforce_updates nicht nötig!
                                               
                                                message = self.get_iattr_value(item.conf, 'robvac')
                                                self.logger.debug("Xiaomi_Robvac: Tu dies und das ! Keyword {0} , weil item {1} geändert wurde   ".format(message, item))
                                                
                                                if message == 'fanspeed':
                                                    self.vakuum.set_fan_speed(item())
                                                    self.logger.debug("Xiaomi_Robvac: {0} geaendert wurde ".format(self.vakuum.fan_speed()))
                                                elif message == 'vol':
                                                    if item() > 100:
                                                        vol = 100
                                                    else:
                                                        vol = item()
                                                    self.vakuum.set_sound_volume(vol)
                                                elif message == 'set_start':
                                                    if item() == True:
                                                        item(False, 'Robvac')
                                                    self.vakuum.start()
                                                elif message == 'set_stop':
                                                    if item() == True:
                                                       item(False, 'Robvac')
                                                    self.vakuum.pause()
                                                elif message == "set_home":
                                                    if item() == True:
                                                       item(False, 'Robvac')
                                                    self.vakuum.home()
                                                elif message == "set_pause":
                                                    if item() == True:
                                                       item(False, 'Robvac')
                                                    self.vakuum.pause()
                                                elif message == "set_spot":
                                                    if item() == True:
                                                       item(False, 'Robvac')
                                                    self.vakuum.spot()
                                                elif message == "set_find":
                                                    if item() == True:
                                                       item(False, 'Robvac')
                                                    self.vakuum.find()
                                                elif message == "reset_filtertimer":
                                                    if item() == True:
                                                       item(False, 'Robvac')                    
                                                    self.vakuum.reset_consumable()
                                                elif message == "disable_dnd":
                                                    if item() == True:
                                                       item(False, 'Robvac')
                                                    self.vakuum.disable_dnd()
                                                    
                                                elif message == "set_dnd":
                                                
                                                    if item() == True:
                                                       item(False, 'Robvac')
                                                    #start_hr, start_min, end_hr, end_min
                                                    self.vakuum.set_dnd(item()[0], item()[1],item()[2], item()[3])
                                                elif message == "clean_zone":
                                                #Clean zones. :param List zones: List of zones to clean: [[x1,y1,x2,y2, iterations],[x1,y1,x2,y2, iterations]]
                                                    self.vakuum.zoned_clean(item()[0], item()[1],item()[2], item()[3], item()[4])
                                                elif message == "go_to":    
                                                    self.vakuum.goto(item()[0], item()[1])
                                                elif message == "create_nogo_zones":
                                                    self.vakuum.create_nogo_zone(item()[0], item()[1])
                                                    pass
                                                    
                                    def run(self):
                                        self.alive = True
                                        self.logger.debug("Xiaomi_Robvac: Found items{}".format(self.messages))
                                        
                                    def stop(self):
                                        self.alive = False
                                        
                                    def parse_item(self, item):
                                        if self.has_iattr(item.conf, 'robvac'):
                                            message = self.get_iattr_value(item.conf, 'robvac')
                                            self.logger.debug("Xiaomi_Robvac: {0} keyword {1}".format(item, message))
                                
                                            if not message in self.messages:
                                                self.messages[message] = item
                                                
                                            return self.update_item
                                
                                    def update_item_read(self, item, caller=None, source=None, dest=None):
                                        if self.has_iattr(item.conf, 'robvac'):
                                            for message in item.get_iattr_value(item.conf, 'robvac'):
                                            #for message in item.conf['robvac']:  # send status update
                                                self.logger.debug("Xiaomi_Robvac: update_item_read {0}".format(message))
                                # ------------------------------------------
                                #    Webinterface Methoden
                                # ------------------------------------------   
                                
                                    def get_connection_info(self):
                                        info = {}
                                        info['ip'] = self._ip
                                        info['token'] = self._token
                                        info['cycle'] = self._cycle
                                        info['connected'] = self._connected
                                        return info
                                        
                                    def init_webinterface(self):
                                        """"
                                        Initialize the web interface for this plugin
                                
                                        This method is only needed if the plugin is implementing a web interface
                                        """
                                        try:
                                            self.mod_http = Modules.get_instance().get_module(
                                                'http')  # try/except to handle running in a core version that does not support modules
                                        except:
                                            self.mod_http = None
                                        if self.mod_http == None:
                                            self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname()))
                                            return False
                                
                                        # set application configuration for cherrypy
                                        webif_dir = self.path_join(self.get_plugin_dir(), 'webif')
                                        config = {
                                            '/': {
                                                'tools.staticdir.root': webif_dir,
                                            },
                                            '/static': {
                                                'tools.staticdir.on': True,
                                                'tools.staticdir.dir': 'static'
                                            }
                                        }
                                        
                                        self.logger.debug("Plugin '{0}': {1}, {2}, {3}, {4}, {5}".format(self.get_shortname(), webif_dir, self.get_shortname(),config,  self.get_classname(), self.get_instance_name()))
                                        # Register the web interface as a cherrypy app
                                        self.mod_http.register_webif(WebInterface(webif_dir, self),
                                                                     self.get_shortname(),
                                                                     config,
                                                                     self.get_classname(), self.get_instance_name(),
                                                                     description='')
                                
                                        return True
                                
                                
                                # ------------------------------------------
                                #    Webinterface of the plugin
                                # ------------------------------------------
                                
                                import cherrypy
                                from jinja2 import Environment, FileSystemLoader
                                
                                class WebInterface(SmartPluginWebIf):
                                
                                
                                    def __init__(self, webif_dir, plugin):
                                        """
                                        Initialization of instance of class WebInterface
                                
                                        :param webif_dir: directory where the webinterface of the plugin resides
                                        :param plugin: instance of the plugin
                                        :type webif_dir: str
                                        :type plugin: object
                                        """
                                        self.logger = logging.getLogger(__name__)
                                        self.webif_dir = webif_dir
                                        self.plugin = plugin
                                        self.tplenv = self.init_template_environment()
                                        self.logger.debug("Plugin : Init Webif")
                                        self.items = Items.get_instance()
                                        
                                    @cherrypy.expose
                                    def index(self, reload=None):
                                        """
                                        Build index.html for cherrypy
                                        Render the template and return the html file to be delivered to the browser
                                        :return: contents of the template after beeing rendered
                                        """
                                        plgitems = []
                                        for item in self.items.return_items():
                                            if ('robvac' in item.conf):
                                                plgitems.append(item)
                                        self.logger.debug("Plugin : Render index Webif")
                                        tmpl = self.tplenv.get_template('index.html')
                                        return tmpl.render(plugin_shortname=self.plugin.get_shortname(),
                                                            plugin_version=self.plugin.get_version(),
                                                            plugin_info=self.plugin.get_info(),
                                                            p=self.plugin,
                                                            connection = self.plugin.get_connection_info(),
                                                            webif_dir = self.webif_dir ,
                                                            items=sorted(plgitems, key=lambda k: str.lower(k['_path'])))

                                Kommentar

                                Lädt...
                                X