Hallo,
ich schlage Ihnen ein Tutorial zum Senden von Daten eines Roborock S51-Roboterstaubsaugers unter Valetudo an Gladys über MQTT vor.
Falls Ihr Roboter nicht mit Valetudo kompatibel ist, kann der Code an Ihre Bedürfnisse angepasst werden, er dient Ihnen als Grundlage.
TUTORIAL Nr. 4: Verwaltung Ihres Roboterstaubsaugers unter Valetudo in Gladys.
EDIT 28/06/2023: Komplette Überarbeitung der Datei RobotAspiToGladys.sh, die die Nutzung vereinfacht
EDIT 25/06/2023: Codeänderungen (JsonArrayToString u. a.), Informationen zu Valetudo RE sowie zur Karte
Roboterstaubsauger-Seite:
Valetudo RE muss darauf installiert werden.
Valetudo (für den Installationsteil): https://valetudo.cloud/pages/general/getting-started.html
Valetudo RE: GitHub - rand256/valetudo: Valetudo RE - experimental vacuum software, cloud free · GitHub
MQTT-Befehle Valetudo RE: MQTT API · rand256/valetudo Wiki · GitHub
Ich musste die MQTT-Verbindung in Valetudo RE konfigurieren.
URL: mqtt://gladys:XYZ@192.168.XXX.XXX:1883
Ich habe die Grundkonfiguration nicht geändert:
Benutzername: rockrobo
Topic-Präfix: valetudo
Autokonfigurations-Präfix: homeassistant
BASH-Seite:
- Gemeinsame Datei: /opt/mosquitto/MQTTConfig.sh
Ich werde die gemeinsame Datei verwenden, die ich in meinen anderen Tutorials vorgeschlagen habe: [TUTO] Partage d'informations entre BASH et Gladys
Sie ermöglicht es, die Anwesenheit von Befehlen zu testen, einen Austausch der Verbindungsvariablen zu Gladys zu haben und Farbe in die Nachrichten zu bringen.
Dort müssen Sie den folgenden Code im Block « Variablen zum Anpassen » hinzufügen:
# Abkürzungen für Gladys-Topics
GladysSet="gladys/master/device"
GladysGet="gladys/device"
# Abkürzungen für MQTT-Geräte
AspiRobot="mqtt:salle:aspirobot/feature/mqtt:aspirobot"
AspiRobot muss an Ihr Topic angepasst werden.
Es scheint auch, dass die Variable ORANGE geändert werden muss auf:
ORANGE="\e[1m\e[38;5;202m"
- Bash-Skript: /opt/mosquitto/RobotAspiToGladys.sh
Die Idee ist, eine Schleife zu erstellen, die die Ankunft von Informationen überwacht, um sie in Gladys anzuzeigen.
Das Skript wird alle Informationen, die es findet, an Gladys senden, die nur die angezeigten aktualisieren wird.
jq wird ein assoziatives Array mit allen Schlüsseln und Werten füllen, die es für jedes Thema findet.
Dieser Themenbegriff ist wichtig, da er in Gladys verwendet wird.
Es ist möglich, die Werte (z.B. Datumsformat) und die Typen (Text oder Zustand) anzupassen.
Man sollte den Code etwas anschauen, der normalerweise recht detailliert ist.
Das Skript muss beim Start des PCs/Raspberry automatisiert werden.
Erfordert die Befehle mosquitto_pub und mosquitto_sub (Debian-Paket mosquitto-clients) sowie jq (Debian-Paket jq).
#!/bin/bash
#########################################################
## Weiterleitung der Informationen des Staubsaugers an Gladys ##
#########################################################
# Benötigte Pakete: mosquitto-clients jq
# Beim Start auszuführen, seine unendliche Schleife überwacht ständig, was passiert
# Laden der gemeinsamen Datei
source /opt/mosquitto/MQTTConfig.sh
# Überprüfung der Anwesenheit der Abhängigkeiten
! CommandCheck "mosquitto_pub:mosquitto-clients" "mosquitto_sub:mosquitto-clients" "jq:jq" && exit 1
### Variablen zur Anpassung
# Abkürzungsvariable, definiert in Valétudo
ValeRock="valetudo/rockrobo"
# Variablen für die Verkettung zu Text beim Abrufen von Werten im JSON-Array-Format
ValueSeparator=", "
LineSeparator="@"
### Variablen zur Anpassung
# Berechnungen für die Erstellung der Tabelle
TerminalWidth=$(($(tput cols) - 2 - 54))
printf -v ColumnValueDash '─%.0s' $(seq 1 ${TerminalWidth})
printf -v ColumnValueSpace ' %.0s' $(seq 1 $(( ${TerminalWidth} - 8 )))
# Anzeige der Tabellenüberschriften
echo "Basis des Themas: ${GladysSet}/${AspiRobot}:"
echo "┌─────────────────────────────────────────────┬───────┬${ColumnValueDash}┐"
echo -e "│ ${ORANGE}Thema ${RAZ} │ ${FUCHSIA}Typ${RAZ} │ ${BLEUFONCE}Wert${RAZ} ${ColumnValueSpace}│"
echo "├─────────────────────────────────────────────┼───────┼${ColumnValueDash}┤"
# Absteigende Funktion in den Objekten {} und die Schlüssel und Unterschlüssel in einem Array mit ihrem Wert hinzufügt
function AutoJsonReader()
{
# $1 : Thema / Mutterobjekt
# $2 : JSON-Code
# AllValues : Name der globalen Variable, die gefüllt wird
# Definition der lokalen Variablen
local Key Value Line
# Verwendung von NULL als Trennzeichen, das -j ermöglicht es, keine Zeilenumbrüche zwischen den Einträgen zu haben
mapfile -td '' Lines < <(jq -rj 'to_entries[] | "\(.key)@@@\(.value)\u0000"' <<< "${2}")
# Schleife über den JSON-Code und gibt Schlüssel@@@Wert zurück
for Line in "${Lines[@]}"
do
# Wert des Schlüssels mit Hinzufügen des Mutterschlüssels, falls vorhanden
Key="${1}${Line%%@@@*}"
# Wert des Schlüssels
Value="${Line##*@@@}"
# Wenn der Wert ein Objekt {} ist
if [[ "${Value:0:1}${Value: -1:1}" == '{}' ]]
then
# Startet die Funktion mit diesem Code, um die Unterschlüssel zu füllen
AutoJsonReader "${Key}." "${Value}"
else
# Hinzufügen des (Unter-)Schlüssels und seines Wertes zum Array
AllValues["${Key}"]="${Value}"
fi
done
}
# Funktion, die ein JSON-Array in Text umwandelt
# Das Array kann andere enthalten, aber keine {}
function JsonArrayToString()
{
# Lokale Variablen
local NewString Line
# Wenn das Array ein Unter-Array enthält
if [[ "${1:0:2}" == '[[' ]]
then
# Schleife, die die Arrays einzeln verarbeitet
while read Line
do
# Aufruf der Funktion mit einem Unter-Array und Abrufen seines Textwertes
NewString+="$(JsonArrayToString "${Line}")${LineSeparator:-@}"
done < <(jq -c '.[]' <<< "${1}")
# Rückgabe des endgültigen Textes mit Entfernung des letzten LineSeparator
echo "${NewString/%${LineSeparator:-@}}"
elif [[ "${1:0:1}" == "[" ]]
then
# Umwandlung des Arrays in Text
NewString=$(jq -r --arg Separator "${ValueSeparator:-:}" 'join($Separator)' <<< "${1}")
# Rückgabe des Textes, entweder endgültig oder eines Unter-Arrays
echo "${NewString}"
fi
}
# Schleife über die vom Staubsauger gesendeten Informationen
# ${ValeRock}/map_data nicht verwendet, ersetzt die "Kamera"
while read Topic JSONCode
do
# Behält nur die letzte Ebene des Themas für den Fall
# z. B.: valetudo/rockrobo/state => state
Topic="${Topic##*/}"
# Aufräumen des Arrays
unset AllValues
declare -A AllValues
# Füllen des Arrays
AutoJsonReader "${Topic}:" "${JSONCode}"
# Im Fall des Fehlerfelds wird es nur zurückgegeben, wenn dies der Fall ist, daher wird ihm ein Standardwert gegeben
if [[ ${Topic} == "state" ]]
then
[[ -z ${AllValues["state:error"]} ]] && AllValues["state:error"]="Kein Fehler"
fi
# Schleife über die Feldnamen mit Abrufen.
for Field in "${!AllValues[@]}"
do
# Abrufen des entsprechenden Wertes.
Value="${AllValues[${Field}]}"
# Nachbearbeitung des Wertes einiger Informationen, es reicht aus, ihr Thema als Schlüssel zu verwenden
case "${Field}" in
# Datumsformat
"attributes:last_bin_out"|"attributes:last_bin_full"|"command_status:updated"|"attributes:last_run_stats.endTime"|"attributes:last_run_stats.startTime")
Value=$((Value / 1000 ))
Value=$(date +'%d/%m/%Y' -d "@$Value") ;;
"attributes:last_run_stats.duration") Value=$((Value / 60 )) ;;
esac
# Standard-Typ text
ValueType="text"
TypeSpace=" "
# Wenn man einen text-Typ erzwingen möchte, reicht es aus, Schlüssel durch | getrennt in den @() hinzuzufügen
if [[ "${Field}" != @() ]]
then
# Wenn der Typ numerisch ist, wird er in state umgewandelt
[[ "${Value}" == ?(+|-)+([0-9])?(.|,)*([0-9]) ]] && { ValueType="state"; unset TypeSpace; }
fi
# Verarbeitet keine null-Werte (nicht gefunden)
if [[ ${Value} != "null" ]]
then
# Umwandlung von JSON-Arrays in Text, wenn der Wert mit einem [ beginnt und mit einem ] endet
[[ "${Value:0:1}${Value: -1:1}" == '[]' ]] && Value="$(JsonArrayToString "${Value}")"
# Berechnungen für die Tabelle
printf -v FieldSpace ' %.0s' $(seq 1 $(( 43 - ${#Field} )))
printf -v ValueSpace ' %.0s' $(seq 1 $(( ${#ColumnValueSpace} - ${#Value} + 7)))
# Anzeige der Informationen im Terminal in einer Tabelle
echo -e "│ ${ORANGE}${Field}${RAZ}${FieldSpace} │ ${FUCHSIA}${ValueType}${RAZ}${TypeSpace} │ ${BLEUFONCE}${Value}${RAZ}${ValueSpace}│"
# Senden des Wertes des richtigen Themas an Gladys
# Verwendung von Abkürzungen, um das gesamte Thema zu definieren
# Es ist wichtig, die MQTT-Geräte in Gladys richtig zu konfigurieren, um das richtige Themenformat zu haben
mosquitto_pub -u "${User}" -P "${Pass}" -t "${GladysSet}/${AspiRobot}:${Field}/${ValueType}" -m "${Value}"
# Abrufen des Rückgabewertes des mosquitto_pub-Befehls
MosquittoReturns=${?}
# Zeigt eine Fehlermeldung an, wenn mosquitto einen Fehler hat
(( ${MosquittoReturns} )) && echo -e "[${ROUGE}Fehler${RAZ}] Der Befehl mosquitto_sub hat den Code ${MosquittoReturns} zurückgegeben." 1>&2
fi
done
# Trennzeichen zwischen den Themen
echo "├─────────────────────────────────────────────┼───────┼${ColumnValueDash}┤"
done < <(mosquitto_sub -v -u "${User}" -P "${Pass}" -t ${ValeRock}/state \
-t ${ValeRock}/attributes \
-t ${ValeRock}/command_status \
-t homeassistant/vacuum/valetudo_rockrobo/config)
Wenn man es startet, zeigt es z. B.:
bash RobotAspiToGladys.sh
Die Topics sind wichtig, sie müssen später in Gladys angegeben werden.
- Bash-Skript: /opt/mosquitto/GladysToRobotAspi.sh
Es ist möglich, MQTT-Befehle an Valetudo zu senden.
Im folgenden Code schlage ich drei Aktionen vor, die ausgeführt werden, wenn ich einen Xiaomi-Knopf drücke.
1 Klick (Code 1): start
2 Klicks (Code 2): stop
Langes Drücken (Code 5): Rückkehr zur Basis
Um die Aktionen zu ändern, reicht es aus, die Variable Actions zu ändern.
Es muss sichergestellt werden, dass es beim Starten des PCs/Raspberry automatisiert gestartet wird.
Benötigt die Befehle mosquitto_pub und mosquitto_sub (Debian-Paket mosquitto-clients).
#!/bin/bash
#####################################################################################################
## Überwachung der speziellen Staubsauger-Taste und Auslösen der entsprechenden Aktionen des Staubsaugers ##
#####################################################################################################
# Benötigt das Paket: mosquitto-clients
# Laden der gemeinsamen Datei
source /opt/mosquitto/MQTTConfig.sh
# Überprüfung der Anwesenheit der Befehle
! CommandCheck "mosquitto_pub:mosquitto-clients" "mosquitto_sub:mosquitto-clients" && exit 1
### Variablen zur Anpassung
# Liste der Aktionen, Entsprechung der MQTT-Codes und Befehle
Actions=(null start stop pause locate return_to_base clean_spot)
### Variablen zur Anpassung
# Endlose Schleife zum Abrufen des MQTT-Tastenwerts
while read Wert
do
# Blockieren, wenn der gesendete Code unbekannt ist
if [[ ${Wert} != @([1-6]) ]]
then
echo -e "[${ORANGE}Warnung${RAZ}] Wert ${Wert} unbekannt..." 1>&2
continue
fi
# Abrufen des Befehls, der dem Tastencode zugeordnet ist
Action="${Actions[${Wert}]}"
# Senden des Befehls an den Staubsauger über den Broker
echo -e "Ausführung der Aktion '${BLEUFONCE}${Action}${RAZ}'."
mosquitto_pub -u "${User}" -P "${Pass}" -t valetudo/rockrobo/command -m ${Action}
# Abrufen des Rückgabewerts des Befehls mosquitto_pub
MosquittoReturns=${?}
# Anzeige einer Fehlermeldung bei einem mosquitto-Fehler
(( ${MosquittoReturns} )) && echo -e "[${ROUGE}Fehler${RAZ}] Der Befehl mosquitto_sub hat den Code ${MosquittoReturns} zurückgegeben." 1>&2
done < <(mosquitto_sub -u "${User}" -P "${Pass}" -t "${GladysGet}/${AspiRobot}:action/state")
Wenn man es ausführt, ergibt sich z. B.:
bash GladysToRobotAspi.sh
Gladys-Seite:
- Erstellung des Staubsaugers auf MQTT-Ebene:
Name: Roboterstaubsauger
Externe ID: mqtt:Raum:aspirobot (mqtt:Raum:Element)
Raum: Raum
In meinem Fall sieht es so aus:
Man muss es an das anpassen, was man in der Variable AspiRobot der Bash-Datei MQTTConfig.sh eingetragen hat
- Erstellung der gewünschten Funktionen mit dem richtigen Typ:
Dieser Schritt wird lange dauern, da alle Funktionen erstellt werden müssen, die mit Gladys verwaltet werden sollen…
Ich habe Blöcke erstellt, um die Informationen zusammenzufassen.
Man muss darauf achten, die richtigen Funktionstypen zu verwenden, damit die empfangenen Daten kompatibel sind.
Batterie, Text, Fläche oder Dauer…
Beispiele für die Formatierung der externen IDs der Funktionen:
Wichtig ist, die Topics zu verwenden, die vom Bash-Skript RobotAspiToGladys.sh angegeben werden, und sie an Gladys zu übergeben.
In meinem Fall sieht es so aus:
- Erstellung der Kamera, die die Karte anzeigt:
Es ist möglich, http://AspiRobotIP/api/simple_map zu verwenden, um die Karte abzurufen, z. B.:
wget http://AspiRobotIP/api/simple_map -O "/tmp/AspiRobotMap.png"
Aber diese fordert alle Minuten ein Bild an, was für den Staubsauger scheinbar schwerwiegend ist.
Es ist möglich, GitHub - rand256/valetudo-mapper: Valetudo companion service · GitHub zu installieren, das eine Karte aus den MQTT-Daten generiert.
Dann kann man die Adresse http://ServerIP:3000/api/map/image (oder Port 3002?) an das Gerät vom Typ Kamera übergeben.
In meinem Fall sieht es so aus:
- Hinzufügen der verschiedenen Funktionen zum Dashboard:
Hier gibt es nichts Besonderes, man muss wie gewohnt vorgehen.
Persönlich habe ich Folgendes gemacht:
- Verwaltung der Aktions-Taste:
Es reicht, eine spezifische Funktion im MQTT-Gerät zu haben (sichtbar in meinem Screenshot)
- Typ: Unbekannt
- Name: Aktion
- ID: mqtt:aspirobot:action
- Werte: von 1 bis 10
- Ist es ein Sensor? Nein
Einen Auslöser wie eine Taste zu haben (AspiRobot-Taste in meinem Fall, mit einem schönen Fehler
)
Eine Szene beim Drücken der Taste zu erstellen, die den Aktionscode an die oben genannte Funktion sendet:
Der Code wird von der Datei /opt/mosquitto/GladysToRobotAspi.sh empfangen.
Ich hoffe, dass dies zumindest als Grundlage oder als Ausgangsidee für andere Staubsauger dienen kann.
Valetudo:
Wenn Sie diese Version verwenden, scheint es viele Informationen zu geben: https://valetudo.cloud/pages/integrations/mqtt.html#capabilities
Danke an: Faire communiquer votre aspirateur robot Xiaomi Roborock en MQTT
Weitere Tutorials:
TUTORIAL Nr. 1: Anzeigen der Temperatur des Raspberry in Gladys.
TUTORIAL Nr. 2: Ausführen eines Bash-Befehls über eine Gladys-Aktion.
TUTORIAL Nr. 3: Anzeigen der Anwesenheit eines Benutzers über das WLAN seines Telefons.






