Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. Xiaomi Saugroboter Fehlermeldung Telegram

    NEWS

    • [erledigt] 15. 05. Wartungsarbeiten am ioBroker Forum

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    Xiaomi Saugroboter Fehlermeldung Telegram

    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      seppel786 last edited by

      Hallo zusammen,

      ich habe von MeisterTR das Skript zum Anzeigen der Saugkarte bei mir eingebunden.

      https://github.com/MeisterTR/ioB-scripts/tree/master/Rockrobo_map

      Dazu habe ich folgendes Skript (siehe Github) eingebunden.

      createState('vis.RockroboMap', '');
      
      var fs = require("fs");
      
      
      const {
          createCanvas,
          Canvas
      } = require('canvas')
      const {
          Image
      } = require('canvas')
      const request = require('request');
      const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
      
      //________________________________________________________________________________________________________________________________________________
      // Farben änder
      const COLOR_FLOOR = "#23465e";
      const COLOR_WALLS = "#2b2e30";
      const COLOR_PATH = "white";
      
      // Telegram
      const SENDTELEGRAM = true;
      const FINISHTEXT = 'Saugen erfolgreich beendet!'
      const ERRORTEXT = 'Beim Saugen ist ein Fehler aufgetreten!'
      
      //________________________________________________________________________________________________________________________________________________
      
      
      
      //Robot Image
      const rocky = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAfCAMAAAHGjw8oAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADbUExURQAAAICAgICAgICAgICAgICAgHx8fH19fX19fYCAgIGBgX5+foCAgH5+foCAgH9/f39/f35+foCAgH9/f39/f4CAgH5+foGBgYCAgICAgIGBgX9/f39/f35+foCAgH9/f39/f4CAgIODg4eHh4mJiZCQkJycnJ2dnZ6enqCgoKSkpKenp62trbGxsbKysry8vL29vcLCwsXFxcbGxsvLy87OztPT09XV1d/f3+Tk5Ojo6Ozs7O3t7e7u7vHx8fLy8vPz8/X19fb29vf39/j4+Pn5+f39/f7+/v///9yECocAAAAgdFJOUwAGChgcKCkzOT5PVWZnlJmfsLq7wcrS1Nre4OXz+vr7ZhJmqwAAAAlwSFlzAAAXEQAAFxEByibzPwAAAcpJREFUKFNlkolaWkEMhYPggliBFiwWhGOx3AqCsggI4lZt8/5P5ElmuEX5P5hMMjeZJBMRafCvUKnbIqpcioci96owTQWqP0QKC54nImUAyr9k7VD1me4YvibHlJKpVUzQhR+dmdTRSDUvdHh8NK8nhqUVch7cITmXA3rtYDmH+3OL4XI1T+BhJUcXczQxOBXJuve0/daeUr5A6g9muJzo5NI2kPKtyRSGBStKQZ5RC1hENWn6NSRTrDUqLD/lsNKoFTNRETlGMn9dDoGdoDcT1fHPi7EuUDD9dMBw4+6vMQVyInnPXDsdW+8tjWfbYTbzg/OstcagzSlb0+wL/6k+1KPhCrj6YFhzS5eXuHcYNF4bsGtDYhFLTOSMqTsx9e3iyKfynb1SK+RqtEq70RzZPwEGKwv7G0OK1QA42Y+HIgct9P3WWG9ItI/mQTgvoeuWAMdlTRclO/+Km2jwlhDvinGNbyJH6EWV84AJ1wl8JowejqTqTmv+0GqDmVLlg/wLX5Mp2rO3WRs2Zs5fznAVd1EzRh10OONr7hhhM4ctevhiVVxHdYsbq+JzHzaIfdjs5CZ9tGInSfoWEXuL7//fwtn9+Jp7wSryDjBFqnOGeuUxAAAAAElFTkSuQmCC";
      const charger = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAdVBMVEUAAAA44Yo44Yo44Yo44Yo44Yo44Yo44Yo44Yp26q844Yr///9767Kv89DG9t2g8Md26q5C44/5/vvz/fjY+ei19NNV5ZtJ45T2/fmY78KP7r1v6atq6Kjs/PPi+u7e+uvM9+Gb8MSS7r+H7bhm6KVh56JZ5p3ZkKITAAAACnRSTlMABTr188xpJ4aepd0A4wAAANZJREFUKM9VklmCgzAMQwkQYCSmLKWl2+zL/Y9YcIUL7wvkJHIUJyKkVcyy+JIGCZILGF//QLEqlTmMdsBEXi56igfH/QVGqvXSu49+1KftCbn+dtxB5LOPfNGQNRaKaQNkTJ46OMGczZg8wJB/9TB+J3nFkyqJMp44vBrnWYhJJmOn/5uVzAotV/zACnbUtTbOpHcQzVx8kxw6mavdpYP90dsNcE5k6xd8RoIb2Xgk6xAbfm5C9NiHtxGiXD/U2P96UJunrS/LOeV2GG4wfBi241P5+NwBnAEUFx9FUdUAAAAASUVORK5CYII=";
      
      //last map
      let last_map;
      
      var canvasimg = new Canvas();
      var ctximg = canvasimg.getContext('2d');
      var res = {};
      
      var img = new Image(); // Create a new Image
      img.src = rocky
      
      const img_charger = new Image();
      img_charger.src = charger;
      
      const robotIp = "192.168.178.87"; // IP of the robot
      const robotState = "mihome-vacuum.0.info.state" // e.g : "mihome-vacuum.0.info.state"
      
      httpGetAsync("http://" + robotIp + "/api/map/latest", updateMapPage);
      
      
      // get actuel map data from Valetudo
      function httpGetAsync(theUrl, callback) {
          var xmlHttp = new XMLHttpRequest();
          var jdata = {};
          xmlHttp.onreadystatechange = function () {
              //console.log(JSON.stringify(xmlHttp));
              if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                  try {
                      jdata = JSON.parse(xmlHttp.responseText)
                      //console.log(JSON.stringify(jdata));
                  } catch (err) {}
                  callback(jdata);
              }
      
          }
          xmlHttp.open("GET", theUrl, true); // true for asynchronous 
          xmlHttp.send(null);
      }
      
      function updateMapPage(res) {
          var canvas = createCanvas();
          var ctx = canvas.getContext('2d');
      
          let mapImageData;
          var map;
          canvas.height = 1024 * 4 //res.image.dimensions.height;
          canvas.width = 1024 * 4 //res.image.dimensions.width;
      
          // Male Boden
          if (res.image.pixels.floor && res.image.pixels.floor.length !== 0) {
              ctx.fillStyle = COLOR_FLOOR;
              res.image.pixels.floor.forEach(function (coord) {
                  ctx.fillRect(coord[0] * 4 + res.image.position.left * 4, coord[1] * 4 + res.image.position.top * 4, 4, 4);
      
              });
          }
          // Male Wände
          if (res.image.pixels.obstacle_strong && res.image.pixels.obstacle_strong.length !== 0) {
              ctx.fillStyle = COLOR_WALLS;
              res.image.pixels.obstacle_strong.forEach(function (coord) {
                  ctx.fillRect(coord[0] * 4 + res.image.position.left * 4, coord[1] * 4 + res.image.position.top * 4, 4, 4);
      
              });
          }
      
          // Male den Pfad
          if (res.path.points && res.path.points.length !== 0) {
              ctx.fillStyle = COLOR_PATH;
              let first = true;
              let cold1, cold2;
      
      
      
              res.path.points.forEach(function (coord) {
                  if (first) {
                      ctx.fillRect(coord[0] / 12.5, coord[1] / 50, 2, 2);
                      cold1 = coord[0] / 12.5;
                      cold2 = coord[1] / 12.5;
                  } else {
                      ctx.beginPath();
                      ctx.lineWidth = 1;
                      ctx.strokeStyle = "#FFFFFF";
                      ctx.moveTo(cold1, cold2);
                      ctx.lineTo(coord[0] / 12.5, coord[1] / 12.5);
                      ctx.stroke();
      
                      cold1 = coord[0] / 12.5
                      cold2 = coord[1] / 12.5
                  }
                  first = false
      
              });
          }
          // Zeichne Roboter
          ctx.beginPath();
          if (res.robot) {
              if (res.path.current_angle && typeof res.robot[0] !== "undefined" && typeof res.robot[1] !== "undefined") {
                  canvasimg = rotateRobo(img, res.path.current_angle);
                  ctx.drawImage(canvasimg, res.robot[0] / 12.5 - 15, res.robot[1] / 12.5 - 15, img.width, img.height);
              } else {
                  ctx.drawImage(img, res.robot[0] / 12.5 - 15, res.robot[1] / 12.5 - 15, img.width, img.height);
              }
          }
          // Zeichne Ladestation wenn vorhanden
          if (res.charger) {
              if (typeof res.charger[0] !== "undefined" && typeof res.charger[1] !== "undefined") {
                  ctx.beginPath();
                  ctx.drawImage(img_charger, res.charger[0] / 12.5 - 15, res.charger[1] / 12.5 - 15);
              }
          }
      
      
      
          // crop image
          let canvas_final = createCanvas();
          let ctx_final = canvas_final.getContext('2d');
          var trimmed = ctx.getImageData(res.image.position.left * 4, res.image.position.top * 4, res.image.dimensions.width * 4, res.image.dimensions.height * 4);
      
          canvas_final.height = res.image.dimensions.height * 4;
          canvas_final.width = res.image.dimensions.width * 4;
      
          ctx_final.putImageData(trimmed, 0, 0);
      
      
          map = canvas_final.toDataURL();
          last_map = canvas_final;
           setState("javascript.0.vis.RockroboMap", '<img src="' + canvas_final.toDataURL() + '" /style="width: auto ;height: 100%;">');
          //log('<img src="' + canvas_final.toDataURL() + '" />');
      }
      
      function send(canvas, text) {
          var buf = canvas.toBuffer();
          fs.writeFile("/opt/iobroker/vac_map.png", buf, (err) => {
              if (err) throw err;
              log('The file has been saved!');
          });
          setTimeout(function () {
              // sendTo('telegram.0', '/opt/iobroker/vac_map.png');
              sendTo('telegram.0', {
                  text: '/opt/iobroker/vac_map.png',
                  caption: text
              });
          }, 3000);
      
      }
      
      function rotateRobo(img, angle) {
          var canvasimg = createCanvas(img.width, img.height);
          var ctximg = canvasimg.getContext('2d');
          const offset = 90;
      
          ctximg.clearRect(0, 0, img.width, img.height);
          ctximg.translate(img.width / 2, img.width / 2);
          ctximg.rotate((angle + offset) * Math.PI / 180);
          ctximg.translate(-img.width / 2, -img.width / 2);
          ctximg.drawImage(img, 0, 0);
          return canvasimg;
      }
      schedule("*/2 * * * * *", function () {
          var robyState = getState(robotState).val;
      
          if (robyState === 5 || robyState === 11 || robyState === 17) httpGetAsync("http://" + robotIp + "/api/map/latest", updateMapPage);
      });
      
      subscribe({
          id: 'mihome-vacuum.0.info.state' /*Vacuum state*/ ,
          change: "ne"
      }, function (obj) {
          if (SENDTELEGRAM) {
              if (obj.newState.val === 8 && obj.oldState.val !== 8) {
                  send(last_map, FINISHTEXT);
              } else if ((obj.oldState.val === 5 || obj.oldState.val === 11 || obj.oldState.val === 17) && obj.newState.val !== 6) {
                  send(last_map,getState("javascript.0.scriptEnabled.Xiaomi.Fehler_Text").val);
              }
          }
      
      });
      

      Dieses Skript sendet nun bei einem Fehler des Saugvorganges ein Nachricht per Telegram mit einer Map.
      Ich möchte nun zusätzlich den Fehlerstatus hinzufügen. Dazu habe ich einen neuen Datenpunkt ("javascript.0.scriptEnabled.Xiaomi.Fehler_Text) erstellt, der
      mit dem Fehlertext gefüllt wird. Diesen Datenpunkt habe ich in Zeile 206 in der Ausgabe im Skript hinzugefügt.
      Wenn ich nun einen Fehler beim Saugvorgang "produziere", ändert sich der Statustext im Datenpunkt, allerdings
      wird beim Versand der Telegramnachricht der alte Status versendet.

      Beispiel:

      Status des DP vor dem Fehler: No Error
      Status des DP beim Fehler: Wheels on top of void, move robot

      Versand via Telegram -> No Error, obwohl Wheels on top of void, move robot in der Nachricht stehen sollte.
      Kann mir da vlt irgendjemand ein bissl behilflich sein. Ich bin in Javascript noch ziemlich grün hinter den Ohren 🙂

      Vielen Dank für Eure Hilfe,
      Seppel

      T 1 Reply Last reply Reply Quote 0
      • T
        ticaki Developer @seppel786 last edited by ticaki

        @seppel786
        Ich denke "mihome-vacuum.0.info.state" wird vor "javascript.0.scriptEnabled.Xiaomi.Fehler_Text" aktualisiert, eine kurze Verzögerung des Versands sollte das Problem beheben.

        setTimeout(() => {
          send(last_map,getState("javascript.0.scriptEnabled.Xiaomi.Fehler_Text").val);
        },20);
        

        EDIT: btw. states unterhalb von javascript.0.scriptEnabled zu verwenden ist AFAIK nicht gut.

        S 1 Reply Last reply Reply Quote 0
        • S
          seppel786 @ticaki last edited by

          @ticaki
          Vielen Dank für deine Antwort.
          Die Verzögerung des Versand hat das Problem tatsächlich gelöst 🙂

          PS: Vielen Dank auch noch für den Tipp mit der Plazierung der eigenen Datenpunkte. Ich den Datenpunkt an einer anderen Stelle eingefügt.
          Sollte besser sein oder?

          abd6b8ee-301a-4d45-b235-95afe4ad2804-grafik.png

          Gruß Seppel

          1 Reply Last reply Reply Quote 1
          • First post
            Last post

          Support us

          ioBroker
          Community Adapters
          Donate

          533
          Online

          31.6k
          Users

          79.5k
          Topics

          1.3m
          Posts

          2
          3
          301
          Loading More Posts
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes
          Reply
          • Reply as topic
          Log in to reply
          Community
          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
          The ioBroker Community 2014-2023
          logo