NEWS

Xiaomi Saugroboter Fehlermeldung Telegram


  • 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


  • @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.


  • @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

Suggested Topics

1.3k
Online

38.3k
Users

43.8k
Topics

611.8k
Posts