Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. Roborock S5 "cleaning area" per Tastendruck?

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.4k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    2.0k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    15
    1
    2.6k

Roborock S5 "cleaning area" per Tastendruck?

Geplant Angeheftet Gesperrt Verschoben Skripten / Logik
javascript
57 Beiträge 9 Kommentatoren 10.3k Aufrufe 15 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • ? Offline
    ? Offline
    Ein ehemaliger Benutzer
    schrieb am zuletzt editiert von
    #1

    Hallo euch allen,

    bei uns wird diese Woche der Roborock S5 einziehen. Nun stehe ich vor folgender Frage:

    in der App kann ich ihm in der Karte eine "Zone" eintragen, in der er JETZT saugen soll, quasi eine "spot cleaning area".

    Nun haben wir regelmäßig Kinder zu Schlafbesuch, welche sagen wir noch Potential haben beim Thema "richtiges Essen mit Sesam- und Mohnbrötchen".

    Gibt es eine Möglichkeit in der vis, wie eben die Zone rund um den Eßtisch dauerhaft definiert wird und per Tastendruck auf dem tablet aktiviert und gesäubert wird?

    Dank euch,

    Frank

    S 1 Antwort Letzte Antwort
    0
    • ? Ein ehemaliger Benutzer

      Hallo euch allen,

      bei uns wird diese Woche der Roborock S5 einziehen. Nun stehe ich vor folgender Frage:

      in der App kann ich ihm in der Karte eine "Zone" eintragen, in der er JETZT saugen soll, quasi eine "spot cleaning area".

      Nun haben wir regelmäßig Kinder zu Schlafbesuch, welche sagen wir noch Potential haben beim Thema "richtiges Essen mit Sesam- und Mohnbrötchen".

      Gibt es eine Möglichkeit in der vis, wie eben die Zone rund um den Eßtisch dauerhaft definiert wird und per Tastendruck auf dem tablet aktiviert und gesäubert wird?

      Dank euch,

      Frank

      S Offline
      S Offline
      Stoni
      schrieb am zuletzt editiert von Stoni
      #2

      @FrankDCE
      Ja gibt es. Nutze ich selber. Allerdings sage ich primär Alexa, sie soll das Esszimmer/Küche/Flur/Haus sauber machen. Das Ziel ist das Gleiche.

      Du musst Dir die FloleVac App runterladen. Da kannst du dann die Koordinaten für den Bereich, der gesaugt werden soll, bestimmen. Dann im iobroker entsprechende Szenen erstellen. Zu guter Letzt in vis mit einem Button diese Szene starten.

      Eine Anleitung findest du im Netz, YouTube oder hier im Forum.

      Guck mal hier:
      https://www.roboter-forum.com/index.php?thread/26292-zonen-reinigung-per-iobroker-alexa-steuern-schritt-für-schritt-anleitung/&postID=389664#post389664

      Gruß Stoni

      K 1 Antwort Letzte Antwort
      0
      • B Offline
        B Offline
        Brati
        schrieb am zuletzt editiert von
        #3

        Hallo,

        lies mal hier:

        https://forum.iobroker.net/post/253807

        Du musst ihn einmal alles reinigen lassen und einstellen, dass die Karte gespeichert wird. Auf Basis dieser Karte liest du die Koordinaten für deinen Bereich aus (per FloleVac App).

        Wenn du einfach nur eine Zone reinigen willst, kannst du diese einfach per Button setzen. Solle es variabel sein, musst du es per Script zusammen basteln.

        Grüße

        Brati

        CCU2 - 46 Geräte, ioBroker auf Intel NUC (DN2820FYKH) mit Tab als Frontend, Projekt Gartenhaus mit HM

        0 1 Antwort Letzte Antwort
        0
        • ? Offline
          ? Offline
          Ein ehemaliger Benutzer
          schrieb am zuletzt editiert von
          #4

          Hallo euch beiden,

          Danke für die Hinweise, werde ich ausprobieren.

          Anschlussfrage: über den Adapter kann ich doch sicher auslesen, wenn der Staubbehälter voll ist. Meine holde möchte den Roboter gern unter dem Sofa parken (ist hoch genug).

          Gibt es eine Möglichkeit, dass er, wenn der Behälter voll ist, zu einer gewissen Koordinate fährt (konkret in die Küche vor den Mülleimer) und da "wartet", bis er geleert wird?

          Und wieso wachsen die Ideen in der smart-home Welt stetig von Tag zu Tag? ;-))

          Dank euch,

          Frank

          B 1 Antwort Letzte Antwort
          0
          • ? Ein ehemaliger Benutzer

            Hallo euch beiden,

            Danke für die Hinweise, werde ich ausprobieren.

            Anschlussfrage: über den Adapter kann ich doch sicher auslesen, wenn der Staubbehälter voll ist. Meine holde möchte den Roboter gern unter dem Sofa parken (ist hoch genug).

            Gibt es eine Möglichkeit, dass er, wenn der Behälter voll ist, zu einer gewissen Koordinate fährt (konkret in die Küche vor den Mülleimer) und da "wartet", bis er geleert wird?

            Und wieso wachsen die Ideen in der smart-home Welt stetig von Tag zu Tag? ;-))

            Dank euch,

            Frank

            B Offline
            B Offline
            Brati
            schrieb am zuletzt editiert von
            #5

            @FrankDCE sagte in Roborock S5 "cleaning area" per Tastendruck?:

            Hallo euch beiden,

            Danke für die Hinweise, werde ich ausprobieren.

            Anschlussfrage: über den Adapter kann ich doch sicher auslesen, wenn der Staubbehälter voll ist. Meine holde möchte den Roboter gern unter dem Sofa parken (ist hoch genug).

            Gibt es eine Möglichkeit, dass er, wenn der Behälter voll ist, zu einer gewissen Koordinate fährt (konkret in die Küche vor den Mülleimer) und da "wartet", bis er geleert wird?

            Und wieso wachsen die Ideen in der smart-home Welt stetig von Tag zu Tag? ;-))

            Dank euch,

            Frank

            Hallo, er meldet nicht, wenn der Behälter voll ist. Meiner parkt auch unter dem Sofa und fährt jeden Samstag um 11 Uhr zum Mülleimer. Ich leere ihn aber trotzdem in der Woche auch mal von Hand, auch hier kommt er auf Tastendruck zum Mülleimer (hab eh einen 6 fach Homematic Taster in der Küche und nutze dafür langen Druck beim Lichtschalter...).

            Vom Prinzip hinterlegst du hier einfach die Koordinaten zum Mülleimer in einem Script (für echte Taster) oder im vis hinter einem Button.

            Grüße

            Brati

            CCU2 - 46 Geräte, ioBroker auf Intel NUC (DN2820FYKH) mit Tab als Frontend, Projekt Gartenhaus mit HM

            ? P 2 Antworten Letzte Antwort
            0
            • B Brati

              @FrankDCE sagte in Roborock S5 "cleaning area" per Tastendruck?:

              Hallo euch beiden,

              Danke für die Hinweise, werde ich ausprobieren.

              Anschlussfrage: über den Adapter kann ich doch sicher auslesen, wenn der Staubbehälter voll ist. Meine holde möchte den Roboter gern unter dem Sofa parken (ist hoch genug).

              Gibt es eine Möglichkeit, dass er, wenn der Behälter voll ist, zu einer gewissen Koordinate fährt (konkret in die Küche vor den Mülleimer) und da "wartet", bis er geleert wird?

              Und wieso wachsen die Ideen in der smart-home Welt stetig von Tag zu Tag? ;-))

              Dank euch,

              Frank

              Hallo, er meldet nicht, wenn der Behälter voll ist. Meiner parkt auch unter dem Sofa und fährt jeden Samstag um 11 Uhr zum Mülleimer. Ich leere ihn aber trotzdem in der Woche auch mal von Hand, auch hier kommt er auf Tastendruck zum Mülleimer (hab eh einen 6 fach Homematic Taster in der Küche und nutze dafür langen Druck beim Lichtschalter...).

              Vom Prinzip hinterlegst du hier einfach die Koordinaten zum Mülleimer in einem Script (für echte Taster) oder im vis hinter einem Button.

              Grüße

              Brati

              ? Offline
              ? Offline
              Ein ehemaliger Benutzer
              schrieb am zuletzt editiert von
              #6

              @Brati Hallo Brati,

              danke für den Hinweis; daran dachte ich auch schon. Aber wenn er an der Koordinate ist, saugt er dann nicht? Oder kann ich ihm sagen "fahr da hin und warte da ohne saugen"?

              B 1 Antwort Letzte Antwort
              0
              • ? Ein ehemaliger Benutzer

                @Brati Hallo Brati,

                danke für den Hinweis; daran dachte ich auch schon. Aber wenn er an der Koordinate ist, saugt er dann nicht? Oder kann ich ihm sagen "fahr da hin und warte da ohne saugen"?

                B Offline
                B Offline
                Brati
                schrieb am zuletzt editiert von
                #7

                @FrankDCE Er fährt einfach zum Punkt und wartet, bzw. geht dann in sleep über. Man sendet nur die GoTo Koordinate und keine Fläche.

                CCU2 - 46 Geräte, ioBroker auf Intel NUC (DN2820FYKH) mit Tab als Frontend, Projekt Gartenhaus mit HM

                1 Antwort Letzte Antwort
                0
                • B Brati

                  @FrankDCE sagte in Roborock S5 "cleaning area" per Tastendruck?:

                  Hallo euch beiden,

                  Danke für die Hinweise, werde ich ausprobieren.

                  Anschlussfrage: über den Adapter kann ich doch sicher auslesen, wenn der Staubbehälter voll ist. Meine holde möchte den Roboter gern unter dem Sofa parken (ist hoch genug).

                  Gibt es eine Möglichkeit, dass er, wenn der Behälter voll ist, zu einer gewissen Koordinate fährt (konkret in die Küche vor den Mülleimer) und da "wartet", bis er geleert wird?

                  Und wieso wachsen die Ideen in der smart-home Welt stetig von Tag zu Tag? ;-))

                  Dank euch,

                  Frank

                  Hallo, er meldet nicht, wenn der Behälter voll ist. Meiner parkt auch unter dem Sofa und fährt jeden Samstag um 11 Uhr zum Mülleimer. Ich leere ihn aber trotzdem in der Woche auch mal von Hand, auch hier kommt er auf Tastendruck zum Mülleimer (hab eh einen 6 fach Homematic Taster in der Küche und nutze dafür langen Druck beim Lichtschalter...).

                  Vom Prinzip hinterlegst du hier einfach die Koordinaten zum Mülleimer in einem Script (für echte Taster) oder im vis hinter einem Button.

                  Grüße

                  Brati

                  P Offline
                  P Offline
                  ple
                  schrieb am zuletzt editiert von
                  #8

                  @Brati sagte in Roborock S5 "cleaning area" per Tastendruck?:

                  @FrankDCE sagte in Roborock S5 "cleaning area" per Tastendruck?:

                  Hallo euch beiden,

                  Danke für die Hinweise, werde ich ausprobieren.

                  Anschlussfrage: über den Adapter kann ich doch sicher auslesen, wenn der Staubbehälter voll ist. Meine holde möchte den Roboter gern unter dem Sofa parken (ist hoch genug).

                  Gibt es eine Möglichkeit, dass er, wenn der Behälter voll ist, zu einer gewissen Koordinate fährt (konkret in die Küche vor den Mülleimer) und da "wartet", bis er geleert wird?

                  Und wieso wachsen die Ideen in der smart-home Welt stetig von Tag zu Tag? ;-))

                  Dank euch,

                  Frank

                  Hallo, er meldet nicht, wenn der Behälter voll ist. Meiner parkt auch unter dem Sofa und fährt jeden Samstag um 11 Uhr zum Mülleimer. Ich leere ihn aber trotzdem in der Woche auch mal von Hand, auch hier kommt er auf Tastendruck zum Mülleimer (hab eh einen 6 fach Homematic Taster in der Küche und nutze dafür langen Druck beim Lichtschalter...).

                  Vom Prinzip hinterlegst du hier einfach die Koordinaten zum Mülleimer in einem Script (für echte Taster) oder im vis hinter einem Button.

                  Grüße

                  Brati

                  Auf die Idee kam ich garnicht, obwohl ich mir 4 mal die Birne angestoßen habe, weil der Sauger unter schwebenden Möbel steht. Jetzt fährt er auch zur Mülltonne mit Alexa, oder 4 Tastern in der Küche :-)
                  Danke für den Tipp.

                  Gruß

                  Intel Nuc + Proxmox

                  ? 1 Antwort Letzte Antwort
                  0
                  • P ple

                    @Brati sagte in Roborock S5 "cleaning area" per Tastendruck?:

                    @FrankDCE sagte in Roborock S5 "cleaning area" per Tastendruck?:

                    Hallo euch beiden,

                    Danke für die Hinweise, werde ich ausprobieren.

                    Anschlussfrage: über den Adapter kann ich doch sicher auslesen, wenn der Staubbehälter voll ist. Meine holde möchte den Roboter gern unter dem Sofa parken (ist hoch genug).

                    Gibt es eine Möglichkeit, dass er, wenn der Behälter voll ist, zu einer gewissen Koordinate fährt (konkret in die Küche vor den Mülleimer) und da "wartet", bis er geleert wird?

                    Und wieso wachsen die Ideen in der smart-home Welt stetig von Tag zu Tag? ;-))

                    Dank euch,

                    Frank

                    Hallo, er meldet nicht, wenn der Behälter voll ist. Meiner parkt auch unter dem Sofa und fährt jeden Samstag um 11 Uhr zum Mülleimer. Ich leere ihn aber trotzdem in der Woche auch mal von Hand, auch hier kommt er auf Tastendruck zum Mülleimer (hab eh einen 6 fach Homematic Taster in der Küche und nutze dafür langen Druck beim Lichtschalter...).

                    Vom Prinzip hinterlegst du hier einfach die Koordinaten zum Mülleimer in einem Script (für echte Taster) oder im vis hinter einem Button.

                    Grüße

                    Brati

                    Auf die Idee kam ich garnicht, obwohl ich mir 4 mal die Birne angestoßen habe, weil der Sauger unter schwebenden Möbel steht. Jetzt fährt er auch zur Mülltonne mit Alexa, oder 4 Tastern in der Küche :-)
                    Danke für den Tipp.

                    Gruß

                    ? Offline
                    ? Offline
                    Ein ehemaliger Benutzer
                    schrieb am zuletzt editiert von
                    #9

                    @Brati @Stoni

                    Sooo .... nachdem der Urlaub vorbei ist mal rangesetzt und - KLAPPT!

                    Dank euch beiden vielmals für die Hinweise!!

                    1 Antwort Letzte Antwort
                    0
                    • ? Offline
                      ? Offline
                      Ein ehemaliger Benutzer
                      schrieb am zuletzt editiert von Ein ehemaliger Benutzer
                      #10

                      So, zu früh gefreut .... ;-)

                      Die Zonenreinigung funktioniert wie gewünscht.

                      Das zum Mülleimer schicken leider nicht.... im Log erscheint die Fehlermeldung

                      "GoTo need two koordinates with type number" - aber er hat doch die beiden Koordinaten, ausgelesen aus der flole vac app; hat mit dem Eßtisch ja auch funktioniert...

                      Die Szene sollte doch auch passen, oder?

                      Nochmals 1.000 Dank!

                      Szene Staubsauger.JPG

                      AlCalzoneA 1 Antwort Letzte Antwort
                      0
                      • ? Ein ehemaliger Benutzer

                        So, zu früh gefreut .... ;-)

                        Die Zonenreinigung funktioniert wie gewünscht.

                        Das zum Mülleimer schicken leider nicht.... im Log erscheint die Fehlermeldung

                        "GoTo need two koordinates with type number" - aber er hat doch die beiden Koordinaten, ausgelesen aus der flole vac app; hat mit dem Eßtisch ja auch funktioniert...

                        Die Szene sollte doch auch passen, oder?

                        Nochmals 1.000 Dank!

                        Szene Staubsauger.JPG

                        AlCalzoneA Offline
                        AlCalzoneA Offline
                        AlCalzone
                        Developer
                        schrieb am zuletzt editiert von
                        #11

                        @FrankDCE sagte in Roborock S5 "cleaning area" per Tastendruck?:

                        GoTo need two koordinates with type number

                        Bin mir gerade nicht sicher... hast du es mal ohne die eckigen Klammern probiert?

                        Warum `sudo` böse ist: https://forum.iobroker.net/post/17109

                        ? 1 Antwort Letzte Antwort
                        0
                        • AlCalzoneA AlCalzone

                          @FrankDCE sagte in Roborock S5 "cleaning area" per Tastendruck?:

                          GoTo need two koordinates with type number

                          Bin mir gerade nicht sicher... hast du es mal ohne die eckigen Klammern probiert?

                          ? Offline
                          ? Offline
                          Ein ehemaliger Benutzer
                          schrieb am zuletzt editiert von
                          #12

                          @AlCalzone

                          Tatsache, das war es. Komisch, im area cleaning sind die auch drin und es klappt.

                          Wie dem auch sei: Danke für den Hinweis.

                          1 Antwort Letzte Antwort
                          0
                          • S Stoni

                            @FrankDCE
                            Ja gibt es. Nutze ich selber. Allerdings sage ich primär Alexa, sie soll das Esszimmer/Küche/Flur/Haus sauber machen. Das Ziel ist das Gleiche.

                            Du musst Dir die FloleVac App runterladen. Da kannst du dann die Koordinaten für den Bereich, der gesaugt werden soll, bestimmen. Dann im iobroker entsprechende Szenen erstellen. Zu guter Letzt in vis mit einem Button diese Szene starten.

                            Eine Anleitung findest du im Netz, YouTube oder hier im Forum.

                            Guck mal hier:
                            https://www.roboter-forum.com/index.php?thread/26292-zonen-reinigung-per-iobroker-alexa-steuern-schritt-für-schritt-anleitung/&postID=389664#post389664

                            Gruß Stoni

                            K Offline
                            K Offline
                            kaiserm
                            schrieb am zuletzt editiert von kaiserm
                            #13

                            @Stoni Genau das hätte ich auch gerne.

                            1. Alles per Sprachbefehle.
                              Also z.B. Alexa, sauge das Esszimmer oder Alexa, sauge das Wohnzimmer
                              Falls alles gereinigt werden soll: Alexa, sauge die Wohnung.

                            Für die Reinigung / Wartung wäre es ideal wenn ich Alexa sagen könnte: Alexa, fahre Hugo (so heisst unser S50) zum Mülleimer.

                            Wie macht man das ?
                            Ok, die Zonen der Zimmer oder Bereiche, also Wohnzimmer, Esszimmer, Mülleimer,...) bekommt man ja in der Flolevac App.

                            Muss man für die komplette Wohnung die Zone über alles ziehen?

                            Was macht man dann mit den ermittelten Zonen?
                            Wo müssen die eingebunden werden damit alles per Sprache läuft?

                            Wenn er vor dem Mülleimer steht und gereinigt wurde müsste man ihn ja mit Alexa, fahre Hugo zur Ladestation zurückschicken können?

                            Weitere Befehle: Alexa, pausiere Saugvorgang oder Alexa, beende Saugvorgang.

                            Was gibt man da wo an ?

                            Man kann ja im Alexa2 Adapter in der Summary immer den letzten Befehl sehen, also kann man darauf triggern und eine Szene abspielen lassen?

                            Danke im Voraus.

                            LG Martin

                            AlCalzoneA S 2 Antworten Letzte Antwort
                            0
                            • B Brati

                              Hallo,

                              lies mal hier:

                              https://forum.iobroker.net/post/253807

                              Du musst ihn einmal alles reinigen lassen und einstellen, dass die Karte gespeichert wird. Auf Basis dieser Karte liest du die Koordinaten für deinen Bereich aus (per FloleVac App).

                              Wenn du einfach nur eine Zone reinigen willst, kannst du diese einfach per Button setzen. Solle es variabel sein, musst du es per Script zusammen basteln.

                              Grüße

                              Brati

                              0 Offline
                              0 Offline
                              0018
                              schrieb am zuletzt editiert von
                              #14

                              @Brati sagte in Roborock S5 "cleaning area" per Tastendruck?:

                              Du musst ihn einmal alles reinigen lassen und einstellen, dass die Karte gespeichert wird.

                              Hi Brati,

                              wo genau kann ich sagen das die Karte gespeichert wird? Hast du evtl einen Screenshot dazu? Behält er dann auch die Karte wenn man den Sauger über den Button am Sauger startet?

                              Mfg
                              0018

                              B 1 Antwort Letzte Antwort
                              0
                              • K kaiserm

                                @Stoni Genau das hätte ich auch gerne.

                                1. Alles per Sprachbefehle.
                                  Also z.B. Alexa, sauge das Esszimmer oder Alexa, sauge das Wohnzimmer
                                  Falls alles gereinigt werden soll: Alexa, sauge die Wohnung.

                                Für die Reinigung / Wartung wäre es ideal wenn ich Alexa sagen könnte: Alexa, fahre Hugo (so heisst unser S50) zum Mülleimer.

                                Wie macht man das ?
                                Ok, die Zonen der Zimmer oder Bereiche, also Wohnzimmer, Esszimmer, Mülleimer,...) bekommt man ja in der Flolevac App.

                                Muss man für die komplette Wohnung die Zone über alles ziehen?

                                Was macht man dann mit den ermittelten Zonen?
                                Wo müssen die eingebunden werden damit alles per Sprache läuft?

                                Wenn er vor dem Mülleimer steht und gereinigt wurde müsste man ihn ja mit Alexa, fahre Hugo zur Ladestation zurückschicken können?

                                Weitere Befehle: Alexa, pausiere Saugvorgang oder Alexa, beende Saugvorgang.

                                Was gibt man da wo an ?

                                Man kann ja im Alexa2 Adapter in der Summary immer den letzten Befehl sehen, also kann man darauf triggern und eine Szene abspielen lassen?

                                Danke im Voraus.

                                LG Martin

                                AlCalzoneA Offline
                                AlCalzoneA Offline
                                AlCalzone
                                Developer
                                schrieb am zuletzt editiert von
                                #15

                                @kaiserm sagte in Roborock S5 "cleaning area" per Tastendruck?:

                                Wie macht man das ?

                                Ich mache das über Alexa-Routinen, die jeweils einen Datenpunkt in ioBroker auf true setzen. Ein JavaScript beobachtet die und startet dann die jeweilige Zonenreinigung. Hierbei wird keine Karte neu generiert.

                                Alles saugen geht über den normalen "start"-Datenpunkt vom Sauger, also keine Zonenreinigung. Dabei wird (zumindest bei mir, 1. Generation) jedes Mal die Karte neu aufgebaut (und so Fehler bereinigt).

                                Alexa, fahre Hugo (so heisst unser S50) zum Mülleimer.

                                Mache noch eine Alexa-Routine, die einen GoTo-Befehl steuert.

                                Wenn er vor dem Mülleimer steht und gereinigt wurde müsste man ihn ja mit Alexa, fahre Hugo zur Ladestation zurückschicken können?
                                Alexa, pausiere Saugvorgang oder Alexa, beende Saugvorgang.

                                Alles Alexa-Routinen, die den jeweiligen DP (Home, Pause, etc...) des Vacuum-Adapters setzen.

                                Warum `sudo` böse ist: https://forum.iobroker.net/post/17109

                                1 Antwort Letzte Antwort
                                0
                                • K Offline
                                  K Offline
                                  kaiserm
                                  schrieb am zuletzt editiert von
                                  #16

                                  Nur nochmal zu meinem Verständnis:

                                  Ich möchte folgendes erreichen:

                                  Alexa, saug die Wohnung - Der S50 soll alles saugen
                                  Alexa, saug das ***zimmer - Der S50 soll das angegebene Zimmer saugen
                                  Alexa, schick Hugo zum Mülleimer - Der S50 (Hugo) fährt zum Mülleimer
                                  Alexa, schick Hugo zum laden - Der S50 (Hugo) fährt zurück zur Ladestation
                                  Alxea, Hugo Pause - Der S50 bleibt stehen
                                  Alexa, Hugo Weiter - Der S50 saugt weiter
                                  Alexa, Hugo Stop - Der S50 stoppt und fährt zurück in die Ladestation

                                  Ich benötige ausser dem Bestätigungston von Alexa eigentlich kein weiteres Gelaber.
                                  Der S50 labert ja selbst auch wenn ihm was nicht passen sollte.

                                  Ich muss also Summary im ersten Fall auf saug UND die UND Wohnung abfragen.

                                  Wenn das wahr ist soll der Sauger die Koordinate ansteuern und lossaugen.

                                  Wie steuert man dann die Koordinaten aus dem Script an?
                                  Habe gelesen das man die Koordinaten über eine Szene übergeben muss?!
                                  In diesem Fall (Wohnung) müsste man nacheinander die Koordinaten aller Zimmer hintereinander in die Szene schreiben.

                                  Kann man per Script dann STEUERE SZENE Sauge_Wohnung mit WAHR ansprechen?

                                  Was muss man für Pausieren, Weiter und Stop ansteuern damit der S50 dies auch macht ?

                                  Danke im Voraus

                                  LG Martin

                                  AlCalzoneA 1 Antwort Letzte Antwort
                                  0
                                  • K kaiserm

                                    Nur nochmal zu meinem Verständnis:

                                    Ich möchte folgendes erreichen:

                                    Alexa, saug die Wohnung - Der S50 soll alles saugen
                                    Alexa, saug das ***zimmer - Der S50 soll das angegebene Zimmer saugen
                                    Alexa, schick Hugo zum Mülleimer - Der S50 (Hugo) fährt zum Mülleimer
                                    Alexa, schick Hugo zum laden - Der S50 (Hugo) fährt zurück zur Ladestation
                                    Alxea, Hugo Pause - Der S50 bleibt stehen
                                    Alexa, Hugo Weiter - Der S50 saugt weiter
                                    Alexa, Hugo Stop - Der S50 stoppt und fährt zurück in die Ladestation

                                    Ich benötige ausser dem Bestätigungston von Alexa eigentlich kein weiteres Gelaber.
                                    Der S50 labert ja selbst auch wenn ihm was nicht passen sollte.

                                    Ich muss also Summary im ersten Fall auf saug UND die UND Wohnung abfragen.

                                    Wenn das wahr ist soll der Sauger die Koordinate ansteuern und lossaugen.

                                    Wie steuert man dann die Koordinaten aus dem Script an?
                                    Habe gelesen das man die Koordinaten über eine Szene übergeben muss?!
                                    In diesem Fall (Wohnung) müsste man nacheinander die Koordinaten aller Zimmer hintereinander in die Szene schreiben.

                                    Kann man per Script dann STEUERE SZENE Sauge_Wohnung mit WAHR ansprechen?

                                    Was muss man für Pausieren, Weiter und Stop ansteuern damit der S50 dies auch macht ?

                                    Danke im Voraus

                                    LG Martin

                                    AlCalzoneA Offline
                                    AlCalzoneA Offline
                                    AlCalzone
                                    Developer
                                    schrieb am zuletzt editiert von
                                    #17

                                    @kaiserm Hier sind die unterschiedlichen Kommandos beschrieben:
                                    https://github.com/iobroker-community-adapters/ioBroker.mihome-vacuum#goto

                                    Ich kann später auch gerne mein Skript zur Verfügung stellen, allerdings kann das noch nicht alles was du dir wünschst. Nur einzelne Räume saugen und zurück zum Dock. Und es benötigt Valetudo auf dem Robbie, da meiner (1. Generation) gerne mal die Karte dreht.

                                    Warum `sudo` böse ist: https://forum.iobroker.net/post/17109

                                    K 1 Antwort Letzte Antwort
                                    0
                                    • AlCalzoneA AlCalzone

                                      @kaiserm Hier sind die unterschiedlichen Kommandos beschrieben:
                                      https://github.com/iobroker-community-adapters/ioBroker.mihome-vacuum#goto

                                      Ich kann später auch gerne mein Skript zur Verfügung stellen, allerdings kann das noch nicht alles was du dir wünschst. Nur einzelne Räume saugen und zurück zum Dock. Und es benötigt Valetudo auf dem Robbie, da meiner (1. Generation) gerne mal die Karte dreht.

                                      K Offline
                                      K Offline
                                      kaiserm
                                      schrieb am zuletzt editiert von kaiserm
                                      #18

                                      @AlCalzone Das wäre Klasse.

                                      Einzelne Räume und zurück zum Dock wäre ja schon mal was.

                                      Pause, Weiter und andere Koordinaten sind ja auch nur weitere Kommandos.

                                      In welchen Datenpunkt muss man denn z.B. pause schreiben damit er pausiert?

                                      Update: Habe gesehen das pause ja ein eigener Datenpunkt ist.

                                      Also müsste ja steuere Datenpunkt mit true den S50 pausieren.

                                      LG Martin

                                      AlCalzoneA 1 Antwort Letzte Antwort
                                      0
                                      • K kaiserm

                                        @AlCalzone Das wäre Klasse.

                                        Einzelne Räume und zurück zum Dock wäre ja schon mal was.

                                        Pause, Weiter und andere Koordinaten sind ja auch nur weitere Kommandos.

                                        In welchen Datenpunkt muss man denn z.B. pause schreiben damit er pausiert?

                                        Update: Habe gesehen das pause ja ein eigener Datenpunkt ist.

                                        Also müsste ja steuere Datenpunkt mit true den S50 pausieren.

                                        LG Martin

                                        AlCalzoneA Offline
                                        AlCalzoneA Offline
                                        AlCalzone
                                        Developer
                                        schrieb am zuletzt editiert von AlCalzone
                                        #19

                                        @kaiserm Also wie versprochen:

                                        Hier die Variante, die bei mir im Einsatz ist (inklusive Test der Kartenorientierung via Valetudo). Muss als TypeScript angelegt werden und benötigt das zusätzliche Paket "axios":

                                        import axios from "axios";
                                        
                                        // Hier den Hostnamen und Zugangsdaten eintragen, unter dem Valetudo erreichbar ist
                                        const roboHostname = "rockrobo.fritz.box";
                                        const valetudoAuth = {
                                        	username: 'valetudo-username',
                                        	password: 'valetudo-password'
                                        }
                                        // Hier den State eintragen, der den aktuellen Sauger-Status angibt
                                        const idVacuumState = "mihome-vacuum.0.info.state";
                                        
                                        const center: Point = [25600, 25600];
                                        // Koordiaten zählen von unten links (0,0) nach oben rechts (51200,51200)
                                        // Die folgenden Koordinaten gehen von nicht rotierter Karte (Winkel 0) aus
                                        const rooms: Record<string, Rectangle[]> = {
                                            "Küche": [[21600, 29100, 23500, 33100]],
                                            "Flur": [[18400, 24000, 22200, 27100], [19500, 27100, 21600, 30400]],
                                            "Wohnzimmer": [[17600, 20000, 21600, 24000], [21600, 19200, 24200, 23200]],
                                            "Schlafzimmer": [[24100, 23200, 26100, 27400], [22100, 23800, 24100, 27400]],
                                            "Bad": [[21500, 27500, 23200, 29000]],
                                        };
                                        
                                        // ===============================================================================
                                        
                                        type Rectangle = [number, number, number, number];
                                        type Point = [number, number];
                                        
                                        /** rotates a rectangle by 90° around the absolute origin */
                                        function rotate90([x1, y1, x2, y2]: Rectangle): Rectangle {
                                            return [-y2, x1, -y1, x2];
                                        }
                                        
                                        /** rotates a rectangle by 180° around the absolute origin */
                                        function rotate180([x1, y1, x2, y2]: Rectangle): Rectangle {
                                            return [-x2, -y2, -x1, -y1];
                                        }
                                        
                                        /** Rotates a rectangle around the given center by the given angle */
                                        function rotate(rect: Rectangle, center: Point, angle: number) {
                                            rect = [rect[0] - center[0], rect[1] - center[1], rect[2] - center[0], rect[3] - center[1]];
                                            if (angle % 180 === 90) {
                                                rect = rotate90(rect);
                                                angle -= 90;
                                            }
                                            if (angle === 180) {
                                                rect = rotate180(rect);
                                            }
                                            rect = [rect[0] + center[0], rect[1] + center[1], rect[2] + center[0], rect[3] + center[1]];
                                            return rect;
                                        }
                                        
                                        for (const room of Object.keys(rooms) as (keyof typeof rooms)[]) {
                                            createState(`Staubsauger.${room}`, {
                                                type: "boolean",
                                                read: true,
                                                write: true,
                                                role: "switch",
                                                name: `${room} saugen`,
                                            });
                                            on({ id: `javascript.${instance}.Staubsauger.${room}`, val: true, ack: false }, async () => {
                                                if (getState(idVacuumState).val !== 8) await cancelCurrentAction();
                                        
                                                if (getMapRotation() === -1 /* unbekannt */) {
                                                    // We need to test the map rotation
                                                    const rotation = await testMapRotation();
                                                    log(`Die Karte ist ${rotation !== 0 ? `um ${rotation}° ` : "nicht "}rotiert.`);
                                                    await rememberMapRotation(rotation);
                                                }
                                        
                                                // Now that we know how the map is rotated, we can clean the room
                                                cleanRoom(room);
                                            });
                                        }
                                        
                                        createState(`Staubsauger.stop`, {
                                            type: "boolean",
                                            read: true,
                                            write: true,
                                            role: "switch",
                                            name: `Staubsauger anhalten`,
                                        });
                                        on({ id: `javascript.${instance}.Staubsauger.stop`, val: true, ack: false }, () => {
                                            stopCleanup();
                                        });
                                        
                                        const idMapRotated = "Staubsauger.info.mapRotated";
                                        createState(idMapRotated, {
                                            type: "number",
                                            read: true,
                                            write: false,
                                            role: "indicator",
                                            states: {
                                                "-1": "unknown",
                                                "0": "Robo links vom Dock",
                                                "90": "Robo unten vom Dock",
                                                "180": "Robo rechts vom Dock",
                                                "270": "Robo oben vom Dock",
                                            },
                                            name: `Wie die Karte rotiert ist`,
                                        });
                                        
                                        /** 
                                         * Bestimmt die Kartenrotation wenn der Staubsauger neben dem Dock steht
                                         * 0 Grad bedeutet, der Sauger steht links
                                         */
                                        async function testMapRotation(): Promise<number> {
                                            log("Teste Kartenorientierung...");
                                            const { data: { charger, robot } } = await axios({
                                                url: `http://${roboHostname}/api/map/latest`,
                                                auth: valetudoAuth
                                            });
                                        
                                            // Valetudo zählt von oben links nach unten rechts, d.h. die Y-Koordinaten
                                            // sind entgegengesetzt der mathematischen Definition
                                            let c2r = [robot[0] - charger[0], charger[1] - robot[1]];
                                            const angle = Math.atan2(c2r[1], c2r[0]) * 180 / Math.PI;
                                            if (angle <= 45 && angle >= -45) {
                                                // Sauger steht rechts
                                                return 180;
                                            } else if (angle > 45 && angle < 135) {
                                                // Sauger steht oben
                                                return 270;
                                            } else if (angle < -45 && angle > -135) {
                                                // Sauger steht unten
                                                return 90;
                                            } else {
                                                return 0;
                                            }
                                        }
                                        
                                        function rememberMapRotation(rotation: number): Promise<void> {
                                            return setStateAsync(idMapRotated, rotation);
                                        }
                                        function getMapRotation(): number {
                                            return getState(idMapRotated).val;
                                        }
                                        
                                        // "Forget" map rotation when the vacuum starts charging
                                        on({ id: idVacuumState, val: 8 /* charging */ }, (obj) => {
                                            setState(idMapRotated, -1 /* unknown */);
                                            // And reset all control states
                                            for (const room of Object.keys(rooms) as (keyof typeof rooms)[]) {
                                                setState(`Staubsauger.${room}`, false, true);
                                            }
                                            setState(`Staubsauger.stop`, false, true);
                                        });
                                        
                                        async function beginCleanup(): Promise<void> {
                                        }
                                        
                                        async function cancelCurrentAction(): Promise<void> {
                                            setState("mihome-vacuum.0.control.pause", true);
                                            // wait for the "paused" status before going home
                                            await waitForPauseOrSleep();
                                        }
                                        
                                        async function stopCleanup(): Promise<void> {
                                            log(`Saugvorgang abgebrochen!`);
                                            setState(`Staubsauger.stop`, true, true);
                                        
                                            if (getState(idVacuumState).val !== 8) {
                                                await cancelCurrentAction();
                                        
                                                await setStateAsync('mihome-vacuum.0.control.home', true);
                                                // wait for the "charging" status before resolving
                                                await waitFor(idVacuumState, 8);
                                            }
                                        
                                            log(`Staubsauger ist in der Basis`);
                                        
                                            setState(`Staubsauger.stop`, false, true);
                                        }
                                        
                                        async function cleanRoom(room: keyof typeof rooms): Promise<void> {
                                            log(`Saugvorgang für ${room} gestartet!`);
                                            setState(`Staubsauger.${room}`, true, true);
                                        
                                            const mapRotation = getMapRotation();
                                            const originalCoords = rooms[room];
                                            log(`original coordinates: ${JSON.stringify(originalCoords)}`);
                                            const roomCoords = rooms[room].map(rect => rotate(rect, center, mapRotation));
                                            log(`rotated coordinates: ${JSON.stringify(roomCoords)}`);
                                        
                                            const coords = roomCoords[0];
                                            const targetCoords = [
                                                ((coords[0] + coords[2]) / 2).toFixed(0),
                                                ((coords[1] + coords[3]) / 2).toFixed(0),
                                            ]
                                        
                                            // go to center of first zone
                                            const gotoString = targetCoords.join(",");
                                            await setStateAsync("mihome-vacuum.0.control.goTo", gotoString);
                                            log(`Fahre zur Mitte von ${room}`);
                                            await wait(10000);
                                            await waitForPauseOrSleep();
                                        
                                            if (getState("Staubsauger.stop").val) return;
                                        
                                            const zoneCleanString = roomCoords.map(zone => {
                                                return "[" + zone.concat(1).map(coord => coord.toString()).join(",") + "]";
                                            }).join(",");
                                        
                                            log("Starte Zonenreinigung...");
                                            await setStateAsync("mihome-vacuum.0.control.zoneClean", zoneCleanString);
                                            // wait for the cleanup to finish
                                            await waitFor(idVacuumState, 6);
                                        }
                                        
                                        async function waitForPauseOrSleep(): Promise<void> {
                                            log("Warte auf Zustand schlafen oder Pause...");
                                            switch (getState(idVacuumState).val) {
                                                case 3:
                                                case 10:
                                                    log(" => Zustand bereits aktiv!");
                                                    return;
                                                default:
                                                    await Promise.race([
                                                        waitFor(idVacuumState, 10),
                                                        waitFor(idVacuumState, 3),
                                                    ]);
                                                    log(" => Zustand erreicht!");
                                            }
                                        }
                                        
                                        function wait(ms: number): Promise<void> {
                                            return new Promise(resolve => {
                                                setTimeout(resolve, ms);
                                            });
                                        }
                                        
                                        function waitFor(stateID: string, value: any): Promise<void> {
                                            return new Promise(resolve => {
                                                const handler = (obj: iobJS.ChangedStateObject) => {
                                                    if (obj.newState.val === value) {
                                                        unsubscribe(handler);
                                                        resolve();
                                                    }
                                                }
                                                subscribe(stateID, handler);
                                            })
                                        }
                                        
                                        function setStateAsync(id: string, state: any): Promise<void> {
                                            return new Promise(res => {
                                                setState(id, state, () => res());
                                            });
                                        }
                                        

                                        Wenn du die automatische Rotation nicht benötigst oder kein Valetudo hast, wäre folgendes die vereinfachte Variante:

                                        // Hier den State eintragen, der den aktuellen Sauger-Status angibt
                                        const idVacuumState = "mihome-vacuum.0.info.state";
                                        
                                        // Koordiaten zählen von unten links (0,0) nach oben rechts (51200,51200)
                                        // Die folgenden Koordinaten gehen von nicht rotierter Karte (Winkel 0) aus
                                        const rooms: Record<string, Rectangle[]> = {
                                        	"Küche": [[21600, 29100, 23500, 33100]],
                                        	"Flur": [[18400, 24000, 22200, 27100], [19500, 27100, 21600, 30400]],
                                        	"Wohnzimmer": [[17600, 20000, 21600, 24000], [21600, 19200, 24200, 23200]],
                                        	"Schlafzimmer": [[24100, 23200, 26100, 27400], [22100, 23800, 24100, 27400]],
                                        	"Bad": [[21500, 27500, 23200, 29000]],
                                        };
                                        
                                        // ===============================================================================
                                        
                                        type Rectangle = [number, number, number, number];
                                        
                                        for (const room of Object.keys(rooms) as (keyof typeof rooms)[]) {
                                        	createState(`Staubsauger.${room}`, {
                                        		type: "boolean",
                                        		read: true,
                                        		write: true,
                                        		role: "switch",
                                        		name: `${room} saugen`,
                                        	});
                                        	on({ id: `javascript.${instance}.Staubsauger.${room}`, val: true, ack: false }, async () => {
                                        		if (getState(idVacuumState).val !== 8) await cancelCurrentAction();
                                        		
                                        		cleanRoom(room);
                                        	});
                                        }
                                        
                                        createState(`Staubsauger.stop`, {
                                        	type: "boolean",
                                        	read: true,
                                        	write: true,
                                        	role: "switch",
                                        	name: `Staubsauger anhalten`,
                                        });
                                        on({ id: `javascript.${instance}.Staubsauger.stop`, val: true, ack: false }, () => {
                                        	stopCleanup();
                                        });
                                        
                                        // Reset all control states when the vacuum starts charging
                                        on({ id: idVacuumState, val: 8 /* charging */ }, (obj) => {
                                        	for (const room of Object.keys(rooms) as (keyof typeof rooms)[]) {
                                        		setState(`Staubsauger.${room}`, false, true);
                                        	}
                                        	setState(`Staubsauger.stop`, false, true);
                                        });
                                        
                                        async function cancelCurrentAction(): Promise<void> {
                                        	setState("mihome-vacuum.0.control.pause", true);
                                        	// wait for the "paused" status before going home
                                        	await waitForPauseOrSleep();
                                        }
                                        
                                        async function stopCleanup(): Promise<void> {
                                        	log(`Saugvorgang abgebrochen!`);
                                        	setState(`Staubsauger.stop`, true, true);
                                        
                                        	if (getState(idVacuumState).val !== 8) {
                                        		await cancelCurrentAction();
                                        
                                        		await setStateAsync('mihome-vacuum.0.control.home', true);
                                        		// wait for the "charging" status before resolving
                                        		await waitFor(idVacuumState, 8);
                                        	}
                                        
                                        	log(`Staubsauger ist in der Basis`);
                                        
                                        	setState(`Staubsauger.stop`, false, true);
                                        }
                                        
                                        async function cleanRoom(room: keyof typeof rooms): Promise<void> {
                                        	log(`Saugvorgang für ${room} gestartet!`);
                                        	setState(`Staubsauger.${room}`, true, true);
                                        
                                        	const roomCoords = rooms[room];
                                        
                                        	const coords = roomCoords[0];
                                        	const targetCoords = [
                                        		((coords[0] + coords[2]) / 2).toFixed(0),
                                        		((coords[1] + coords[3]) / 2).toFixed(0),
                                        	]
                                        
                                        	// go to center of first zone
                                        	const gotoString = targetCoords.join(",");
                                        	await setStateAsync("mihome-vacuum.0.control.goTo", gotoString);
                                        	log(`Fahre zur Mitte von ${room}`);
                                        	await wait(10000);
                                        	await waitForPauseOrSleep();
                                        
                                        	if (getState("Staubsauger.stop").val) return;
                                        
                                        	const zoneCleanString = roomCoords.map(zone => {
                                        		return "[" + zone.concat(1).map(coord => coord.toString()).join(",") + "]";
                                        	}).join(",");
                                        
                                        	log("Starte Zonenreinigung...");
                                        	await setStateAsync("mihome-vacuum.0.control.zoneClean", zoneCleanString);
                                        	// wait for the cleanup to finish
                                        	await waitFor(idVacuumState, 6);
                                        }
                                        
                                        async function waitForPauseOrSleep(): Promise<void> {
                                        	log("Warte auf Zustand schlafen oder Pause...");
                                        	switch (getState(idVacuumState).val) {
                                        		case 3:
                                        		case 10:
                                        			log(" => Zustand bereits aktiv!");
                                        			return;
                                        		default:
                                        			await Promise.race([
                                        				waitFor(idVacuumState, 10),
                                        				waitFor(idVacuumState, 3),
                                        			]);
                                        			log(" => Zustand erreicht!");
                                        	}
                                        }
                                        
                                        function wait(ms: number): Promise<void> {
                                        	return new Promise(resolve => {
                                        		setTimeout(resolve, ms);
                                        	});
                                        }
                                        
                                        function waitFor(stateID: string, value: any): Promise<void> {
                                        	return new Promise(resolve => {
                                        		const handler = (obj: iobJS.ChangedStateObject) => {
                                        			if (obj.newState.val === value) {
                                        				unsubscribe(handler);
                                        				resolve();
                                        			}
                                        		}
                                        		subscribe(stateID, handler);
                                        	})
                                        }
                                        
                                        function setStateAsync(id: string, state: any): Promise<void> {
                                        	return new Promise(res => {
                                        		setState(id, state, () => res());
                                        	});
                                        }
                                        

                                        Beide Varianten legen für jeden Raum und für Stop einen State an, den du dann jeweils mit einer Alexa-Routine ansprechen kannst.

                                        Warum `sudo` böse ist: https://forum.iobroker.net/post/17109

                                        K M 0 Chris_71C 5 Antworten Letzte Antwort
                                        1
                                        • AlCalzoneA AlCalzone

                                          @kaiserm Also wie versprochen:

                                          Hier die Variante, die bei mir im Einsatz ist (inklusive Test der Kartenorientierung via Valetudo). Muss als TypeScript angelegt werden und benötigt das zusätzliche Paket "axios":

                                          import axios from "axios";
                                          
                                          // Hier den Hostnamen und Zugangsdaten eintragen, unter dem Valetudo erreichbar ist
                                          const roboHostname = "rockrobo.fritz.box";
                                          const valetudoAuth = {
                                          	username: 'valetudo-username',
                                          	password: 'valetudo-password'
                                          }
                                          // Hier den State eintragen, der den aktuellen Sauger-Status angibt
                                          const idVacuumState = "mihome-vacuum.0.info.state";
                                          
                                          const center: Point = [25600, 25600];
                                          // Koordiaten zählen von unten links (0,0) nach oben rechts (51200,51200)
                                          // Die folgenden Koordinaten gehen von nicht rotierter Karte (Winkel 0) aus
                                          const rooms: Record<string, Rectangle[]> = {
                                              "Küche": [[21600, 29100, 23500, 33100]],
                                              "Flur": [[18400, 24000, 22200, 27100], [19500, 27100, 21600, 30400]],
                                              "Wohnzimmer": [[17600, 20000, 21600, 24000], [21600, 19200, 24200, 23200]],
                                              "Schlafzimmer": [[24100, 23200, 26100, 27400], [22100, 23800, 24100, 27400]],
                                              "Bad": [[21500, 27500, 23200, 29000]],
                                          };
                                          
                                          // ===============================================================================
                                          
                                          type Rectangle = [number, number, number, number];
                                          type Point = [number, number];
                                          
                                          /** rotates a rectangle by 90° around the absolute origin */
                                          function rotate90([x1, y1, x2, y2]: Rectangle): Rectangle {
                                              return [-y2, x1, -y1, x2];
                                          }
                                          
                                          /** rotates a rectangle by 180° around the absolute origin */
                                          function rotate180([x1, y1, x2, y2]: Rectangle): Rectangle {
                                              return [-x2, -y2, -x1, -y1];
                                          }
                                          
                                          /** Rotates a rectangle around the given center by the given angle */
                                          function rotate(rect: Rectangle, center: Point, angle: number) {
                                              rect = [rect[0] - center[0], rect[1] - center[1], rect[2] - center[0], rect[3] - center[1]];
                                              if (angle % 180 === 90) {
                                                  rect = rotate90(rect);
                                                  angle -= 90;
                                              }
                                              if (angle === 180) {
                                                  rect = rotate180(rect);
                                              }
                                              rect = [rect[0] + center[0], rect[1] + center[1], rect[2] + center[0], rect[3] + center[1]];
                                              return rect;
                                          }
                                          
                                          for (const room of Object.keys(rooms) as (keyof typeof rooms)[]) {
                                              createState(`Staubsauger.${room}`, {
                                                  type: "boolean",
                                                  read: true,
                                                  write: true,
                                                  role: "switch",
                                                  name: `${room} saugen`,
                                              });
                                              on({ id: `javascript.${instance}.Staubsauger.${room}`, val: true, ack: false }, async () => {
                                                  if (getState(idVacuumState).val !== 8) await cancelCurrentAction();
                                          
                                                  if (getMapRotation() === -1 /* unbekannt */) {
                                                      // We need to test the map rotation
                                                      const rotation = await testMapRotation();
                                                      log(`Die Karte ist ${rotation !== 0 ? `um ${rotation}° ` : "nicht "}rotiert.`);
                                                      await rememberMapRotation(rotation);
                                                  }
                                          
                                                  // Now that we know how the map is rotated, we can clean the room
                                                  cleanRoom(room);
                                              });
                                          }
                                          
                                          createState(`Staubsauger.stop`, {
                                              type: "boolean",
                                              read: true,
                                              write: true,
                                              role: "switch",
                                              name: `Staubsauger anhalten`,
                                          });
                                          on({ id: `javascript.${instance}.Staubsauger.stop`, val: true, ack: false }, () => {
                                              stopCleanup();
                                          });
                                          
                                          const idMapRotated = "Staubsauger.info.mapRotated";
                                          createState(idMapRotated, {
                                              type: "number",
                                              read: true,
                                              write: false,
                                              role: "indicator",
                                              states: {
                                                  "-1": "unknown",
                                                  "0": "Robo links vom Dock",
                                                  "90": "Robo unten vom Dock",
                                                  "180": "Robo rechts vom Dock",
                                                  "270": "Robo oben vom Dock",
                                              },
                                              name: `Wie die Karte rotiert ist`,
                                          });
                                          
                                          /** 
                                           * Bestimmt die Kartenrotation wenn der Staubsauger neben dem Dock steht
                                           * 0 Grad bedeutet, der Sauger steht links
                                           */
                                          async function testMapRotation(): Promise<number> {
                                              log("Teste Kartenorientierung...");
                                              const { data: { charger, robot } } = await axios({
                                                  url: `http://${roboHostname}/api/map/latest`,
                                                  auth: valetudoAuth
                                              });
                                          
                                              // Valetudo zählt von oben links nach unten rechts, d.h. die Y-Koordinaten
                                              // sind entgegengesetzt der mathematischen Definition
                                              let c2r = [robot[0] - charger[0], charger[1] - robot[1]];
                                              const angle = Math.atan2(c2r[1], c2r[0]) * 180 / Math.PI;
                                              if (angle <= 45 && angle >= -45) {
                                                  // Sauger steht rechts
                                                  return 180;
                                              } else if (angle > 45 && angle < 135) {
                                                  // Sauger steht oben
                                                  return 270;
                                              } else if (angle < -45 && angle > -135) {
                                                  // Sauger steht unten
                                                  return 90;
                                              } else {
                                                  return 0;
                                              }
                                          }
                                          
                                          function rememberMapRotation(rotation: number): Promise<void> {
                                              return setStateAsync(idMapRotated, rotation);
                                          }
                                          function getMapRotation(): number {
                                              return getState(idMapRotated).val;
                                          }
                                          
                                          // "Forget" map rotation when the vacuum starts charging
                                          on({ id: idVacuumState, val: 8 /* charging */ }, (obj) => {
                                              setState(idMapRotated, -1 /* unknown */);
                                              // And reset all control states
                                              for (const room of Object.keys(rooms) as (keyof typeof rooms)[]) {
                                                  setState(`Staubsauger.${room}`, false, true);
                                              }
                                              setState(`Staubsauger.stop`, false, true);
                                          });
                                          
                                          async function beginCleanup(): Promise<void> {
                                          }
                                          
                                          async function cancelCurrentAction(): Promise<void> {
                                              setState("mihome-vacuum.0.control.pause", true);
                                              // wait for the "paused" status before going home
                                              await waitForPauseOrSleep();
                                          }
                                          
                                          async function stopCleanup(): Promise<void> {
                                              log(`Saugvorgang abgebrochen!`);
                                              setState(`Staubsauger.stop`, true, true);
                                          
                                              if (getState(idVacuumState).val !== 8) {
                                                  await cancelCurrentAction();
                                          
                                                  await setStateAsync('mihome-vacuum.0.control.home', true);
                                                  // wait for the "charging" status before resolving
                                                  await waitFor(idVacuumState, 8);
                                              }
                                          
                                              log(`Staubsauger ist in der Basis`);
                                          
                                              setState(`Staubsauger.stop`, false, true);
                                          }
                                          
                                          async function cleanRoom(room: keyof typeof rooms): Promise<void> {
                                              log(`Saugvorgang für ${room} gestartet!`);
                                              setState(`Staubsauger.${room}`, true, true);
                                          
                                              const mapRotation = getMapRotation();
                                              const originalCoords = rooms[room];
                                              log(`original coordinates: ${JSON.stringify(originalCoords)}`);
                                              const roomCoords = rooms[room].map(rect => rotate(rect, center, mapRotation));
                                              log(`rotated coordinates: ${JSON.stringify(roomCoords)}`);
                                          
                                              const coords = roomCoords[0];
                                              const targetCoords = [
                                                  ((coords[0] + coords[2]) / 2).toFixed(0),
                                                  ((coords[1] + coords[3]) / 2).toFixed(0),
                                              ]
                                          
                                              // go to center of first zone
                                              const gotoString = targetCoords.join(",");
                                              await setStateAsync("mihome-vacuum.0.control.goTo", gotoString);
                                              log(`Fahre zur Mitte von ${room}`);
                                              await wait(10000);
                                              await waitForPauseOrSleep();
                                          
                                              if (getState("Staubsauger.stop").val) return;
                                          
                                              const zoneCleanString = roomCoords.map(zone => {
                                                  return "[" + zone.concat(1).map(coord => coord.toString()).join(",") + "]";
                                              }).join(",");
                                          
                                              log("Starte Zonenreinigung...");
                                              await setStateAsync("mihome-vacuum.0.control.zoneClean", zoneCleanString);
                                              // wait for the cleanup to finish
                                              await waitFor(idVacuumState, 6);
                                          }
                                          
                                          async function waitForPauseOrSleep(): Promise<void> {
                                              log("Warte auf Zustand schlafen oder Pause...");
                                              switch (getState(idVacuumState).val) {
                                                  case 3:
                                                  case 10:
                                                      log(" => Zustand bereits aktiv!");
                                                      return;
                                                  default:
                                                      await Promise.race([
                                                          waitFor(idVacuumState, 10),
                                                          waitFor(idVacuumState, 3),
                                                      ]);
                                                      log(" => Zustand erreicht!");
                                              }
                                          }
                                          
                                          function wait(ms: number): Promise<void> {
                                              return new Promise(resolve => {
                                                  setTimeout(resolve, ms);
                                              });
                                          }
                                          
                                          function waitFor(stateID: string, value: any): Promise<void> {
                                              return new Promise(resolve => {
                                                  const handler = (obj: iobJS.ChangedStateObject) => {
                                                      if (obj.newState.val === value) {
                                                          unsubscribe(handler);
                                                          resolve();
                                                      }
                                                  }
                                                  subscribe(stateID, handler);
                                              })
                                          }
                                          
                                          function setStateAsync(id: string, state: any): Promise<void> {
                                              return new Promise(res => {
                                                  setState(id, state, () => res());
                                              });
                                          }
                                          

                                          Wenn du die automatische Rotation nicht benötigst oder kein Valetudo hast, wäre folgendes die vereinfachte Variante:

                                          // Hier den State eintragen, der den aktuellen Sauger-Status angibt
                                          const idVacuumState = "mihome-vacuum.0.info.state";
                                          
                                          // Koordiaten zählen von unten links (0,0) nach oben rechts (51200,51200)
                                          // Die folgenden Koordinaten gehen von nicht rotierter Karte (Winkel 0) aus
                                          const rooms: Record<string, Rectangle[]> = {
                                          	"Küche": [[21600, 29100, 23500, 33100]],
                                          	"Flur": [[18400, 24000, 22200, 27100], [19500, 27100, 21600, 30400]],
                                          	"Wohnzimmer": [[17600, 20000, 21600, 24000], [21600, 19200, 24200, 23200]],
                                          	"Schlafzimmer": [[24100, 23200, 26100, 27400], [22100, 23800, 24100, 27400]],
                                          	"Bad": [[21500, 27500, 23200, 29000]],
                                          };
                                          
                                          // ===============================================================================
                                          
                                          type Rectangle = [number, number, number, number];
                                          
                                          for (const room of Object.keys(rooms) as (keyof typeof rooms)[]) {
                                          	createState(`Staubsauger.${room}`, {
                                          		type: "boolean",
                                          		read: true,
                                          		write: true,
                                          		role: "switch",
                                          		name: `${room} saugen`,
                                          	});
                                          	on({ id: `javascript.${instance}.Staubsauger.${room}`, val: true, ack: false }, async () => {
                                          		if (getState(idVacuumState).val !== 8) await cancelCurrentAction();
                                          		
                                          		cleanRoom(room);
                                          	});
                                          }
                                          
                                          createState(`Staubsauger.stop`, {
                                          	type: "boolean",
                                          	read: true,
                                          	write: true,
                                          	role: "switch",
                                          	name: `Staubsauger anhalten`,
                                          });
                                          on({ id: `javascript.${instance}.Staubsauger.stop`, val: true, ack: false }, () => {
                                          	stopCleanup();
                                          });
                                          
                                          // Reset all control states when the vacuum starts charging
                                          on({ id: idVacuumState, val: 8 /* charging */ }, (obj) => {
                                          	for (const room of Object.keys(rooms) as (keyof typeof rooms)[]) {
                                          		setState(`Staubsauger.${room}`, false, true);
                                          	}
                                          	setState(`Staubsauger.stop`, false, true);
                                          });
                                          
                                          async function cancelCurrentAction(): Promise<void> {
                                          	setState("mihome-vacuum.0.control.pause", true);
                                          	// wait for the "paused" status before going home
                                          	await waitForPauseOrSleep();
                                          }
                                          
                                          async function stopCleanup(): Promise<void> {
                                          	log(`Saugvorgang abgebrochen!`);
                                          	setState(`Staubsauger.stop`, true, true);
                                          
                                          	if (getState(idVacuumState).val !== 8) {
                                          		await cancelCurrentAction();
                                          
                                          		await setStateAsync('mihome-vacuum.0.control.home', true);
                                          		// wait for the "charging" status before resolving
                                          		await waitFor(idVacuumState, 8);
                                          	}
                                          
                                          	log(`Staubsauger ist in der Basis`);
                                          
                                          	setState(`Staubsauger.stop`, false, true);
                                          }
                                          
                                          async function cleanRoom(room: keyof typeof rooms): Promise<void> {
                                          	log(`Saugvorgang für ${room} gestartet!`);
                                          	setState(`Staubsauger.${room}`, true, true);
                                          
                                          	const roomCoords = rooms[room];
                                          
                                          	const coords = roomCoords[0];
                                          	const targetCoords = [
                                          		((coords[0] + coords[2]) / 2).toFixed(0),
                                          		((coords[1] + coords[3]) / 2).toFixed(0),
                                          	]
                                          
                                          	// go to center of first zone
                                          	const gotoString = targetCoords.join(",");
                                          	await setStateAsync("mihome-vacuum.0.control.goTo", gotoString);
                                          	log(`Fahre zur Mitte von ${room}`);
                                          	await wait(10000);
                                          	await waitForPauseOrSleep();
                                          
                                          	if (getState("Staubsauger.stop").val) return;
                                          
                                          	const zoneCleanString = roomCoords.map(zone => {
                                          		return "[" + zone.concat(1).map(coord => coord.toString()).join(",") + "]";
                                          	}).join(",");
                                          
                                          	log("Starte Zonenreinigung...");
                                          	await setStateAsync("mihome-vacuum.0.control.zoneClean", zoneCleanString);
                                          	// wait for the cleanup to finish
                                          	await waitFor(idVacuumState, 6);
                                          }
                                          
                                          async function waitForPauseOrSleep(): Promise<void> {
                                          	log("Warte auf Zustand schlafen oder Pause...");
                                          	switch (getState(idVacuumState).val) {
                                          		case 3:
                                          		case 10:
                                          			log(" => Zustand bereits aktiv!");
                                          			return;
                                          		default:
                                          			await Promise.race([
                                          				waitFor(idVacuumState, 10),
                                          				waitFor(idVacuumState, 3),
                                          			]);
                                          			log(" => Zustand erreicht!");
                                          	}
                                          }
                                          
                                          function wait(ms: number): Promise<void> {
                                          	return new Promise(resolve => {
                                          		setTimeout(resolve, ms);
                                          	});
                                          }
                                          
                                          function waitFor(stateID: string, value: any): Promise<void> {
                                          	return new Promise(resolve => {
                                          		const handler = (obj: iobJS.ChangedStateObject) => {
                                          			if (obj.newState.val === value) {
                                          				unsubscribe(handler);
                                          				resolve();
                                          			}
                                          		}
                                          		subscribe(stateID, handler);
                                          	})
                                          }
                                          
                                          function setStateAsync(id: string, state: any): Promise<void> {
                                          	return new Promise(res => {
                                          		setState(id, state, () => res());
                                          	});
                                          }
                                          

                                          Beide Varianten legen für jeden Raum und für Stop einen State an, den du dann jeweils mit einer Alexa-Routine ansprechen kannst.

                                          K Offline
                                          K Offline
                                          kaiserm
                                          schrieb am zuletzt editiert von kaiserm
                                          #20

                                          @AlCalzone Vielen Dank.

                                          Ich probiere gerade noch was anderes:

                                          Alexa reagiert und spricht den Text.
                                          Egal wie ich die Koordinaten eingebe. Der S50 macht keinen Mucks.
                                          GFebe ich nur die ersten beiden Punkte ohne Klammern aber mit Komma an fährt er aus der Ladestation, irrt etwas umher und sagt dann er kann nicht zum Ziel fahren.

                                          Man müsste doch in den GoToPoint Datenpunkt direkt die Koordinate reinschreiben können?!

                                          Habe alles probiert. Mit Klammern, ohne ... mit Kommas

                                          Gebe ich ihm nur die ersten beiden Zahlen fährt er aus der Docking Station irrt kurz umher und sagt dann er kann nicht an die Koordinate fahren.

                                          Im Log finde ich immer nur: GoTo only work with two arguments seperated by

                                          LG Martin

                                          fb33cc15-1813-4d1b-bb7d-36794475ee4d-grafik.png

                                          K M 2 Antworten Letzte Antwort
                                          0
                                          Antworten
                                          • In einem neuen Thema antworten
                                          Anmelden zum Antworten
                                          • Älteste zuerst
                                          • Neuste zuerst
                                          • Meiste Stimmen


                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate

                                          396

                                          Online

                                          32.4k

                                          Benutzer

                                          81.4k

                                          Themen

                                          1.3m

                                          Beiträge
                                          Community
                                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                          ioBroker Community 2014-2025
                                          logo
                                          • Anmelden

                                          • Du hast noch kein Konto? Registrieren

                                          • Anmelden oder registrieren, um zu suchen
                                          • Erster Beitrag
                                            Letzter Beitrag
                                          0
                                          • Home
                                          • Aktuell
                                          • Tags
                                          • Ungelesen 0
                                          • Kategorien
                                          • Unreplied
                                          • Beliebt
                                          • GitHub
                                          • Docu
                                          • Hilfe