Xiaomi WiFi Devices Modul (Vacuum/Airpurifier/Fan) - 72_XiaomiDevice (Support)

Begonnen von Markus M., 11 Juni 2017, 12:48:58

Vorheriges Thema - Nächstes Thema

tomcat.x

FHEM: 6.1 auf Raspi 3, Raspbian (Buster), Perl v5.28.1
Sender/Empfänger: 2 x CULv3, Duofern Stick, HM-MOD-RPI-PCB
Gateways: FRITZ!Box 6591 (OS: 7.57), Trädfri, ConBee 2,  piVCCU, OpenMQTTGateway
Sensoren/Aktoren: FRITZ!DECT, FS20, FHT, HMS, HomeMatic, Trädfri, DuoFern, NetAtmo

bismosa

Hallo!

Ich bin auf der Suche nach einer Lösung die Karten auf dem S5 Max zu wechseln auch über diesen Thread gestolpert.
Immer nach einem Wechsel des Stockwerkes kann ich keine Einzelraumreinigung über FHEM starten, da die falsche Karte als Basis verwendet wird.

Da es bisher scheinbar keine einfache Lösung gibt, habe ich mir eine Lösung zusammengeschustert  ;)
Vielleicht hilft dies ja auch dem einen oder anderen  :)
Natürlich wäre es schön, wenn das auch im Modul übernommen werden könnte. Ich habe aber auch gelesen, dass die Entwicklung derzeit eingestellt ist.

Ich nutze einen Weg über python-miio ( https://github.com/rytilahti/python-miio )
Dies muss zunächst installiert werden (bei mir ein Raspberry mit buster):

pip3 install cryptography==35
pip3 install python-miio

cryptography in einer älteren Version, damit nicht im Vorfeld rust installiert werden muss.

Den Rest mache ich mit einem DOIF. Hier habe ich darauf geachtet, dass die Befehle das System nicht ausbremsen. Nach Abruf der Daten werden diese per Telnet an das DOIF gesendet.
<token> mit dem eigentlichen Token ersetzen
<IP> mit der IP-Adresse ersetzen

defmod di_Roborock DOIF
\
getMaps{\
##mystr=`mirobo --ip <IP> --token <token> raw-command get_multi_maps_list 1 | tail -n +2`;;  perl /opt/fhem/fhem.pl 7072 "setreading di_Roborock maps ${mystr}"\
\
my $command="mirobo --ip <IP> --token <token> raw-command get_multi_maps_list 1 | tail -n +2";;\
my $fhemstring="perl /opt/fhem/fhem.pl 7072 \"setreading $SELF maps \${mystr}\"";;\
my $mapdata="mystr=`$command`;; $fhemstring";;\
system ("{ $mapdata;; }&");;\
\
}\
getActiveMap{\
##Keine lesbare Rückmeldung! Nur Inkrement\
my $command="mirobo --ip <IP> --token <token> raw-command get_map_v1 1 | tail -n +2";;\
my $fhemstring="perl /opt/fhem/fhem.pl 7072 \"setreading $SELF activeMap \${mystr}\"";;\
my $mapdata="mystr=`$command`;; $fhemstring";;\
system ("{ $mapdata;; }&");;\
}\
\
setMapUnten{\
my $Num=0;;\
set_Reading("MapLoaded", "false",1);;\
my $command="mirobo --ip <IP> --token <token> raw-command load_multi_map $Num,1 | tail -n +2";;\
my $fhemstring="perl /opt/fhem/fhem.pl 7072 \"setreading $SELF MapLoaded \${mystr}\"";;\
my $mapdata="mystr=`$command`;; $fhemstring";;\
system ("{ $mapdata;; }&");;\
}\
setMapKeller{\
my $Num=1;;\
set_Reading("MapLoaded", "false",1);;\
my $command="mirobo --ip <IP> --token <token> raw-command load_multi_map $Num,1 | tail -n +2";;\
my $fhemstring="perl /opt/fhem/fhem.pl 7072 \"setreading $SELF MapLoaded \${mystr}\"";;\
my $mapdata="mystr=`$command`;; $fhemstring";;\
system ("{ $mapdata;; }&");;\
}\
setMapOben{\
my $Num=2;;\
set_Reading("MapLoaded", "false",1);;\
my $command="mirobo --ip <IP> --token <token> raw-command load_multi_map $Num,1 | tail -n +2";;\
my $fhemstring="perl /opt/fhem/fhem.pl 7072 \"setreading $SELF MapLoaded \${mystr}\"";;\
my $mapdata="mystr=`$command`;; $fhemstring";;\
system ("{ $mapdata;; }&");;\
}
attr di_Roborock room Sauger
attr di_Roborock userReadings MapLoadedTxt:MapLoaded.* {\
my $var=ReadingsVal($name,"MapLoaded","false");;\
$var =~ s/\[\'//g;;\
$var =~ s/\'\]//g;;\
return $var;;\
}

setstate di_Roborock initialized
setstate di_Roborock 2023-01-09 18:45:33 mode enabled
setstate di_Roborock 2023-01-09 18:45:35 state initialized


set di_Roborock getMaps
Erzeugt ein reading im JSON-Format. Hier werden die IDs und die Map-Namen ausgelesen.

set di_Roborock getActiveMap
War mein Versuch, die aktive Karte auszulesen. Bei jedem Auslesen hat man jedoch nur ein Increment. Die aktive Karte kann wohl nicht ausgelesen werden.

set di_Roborock setMapXYZ
Lädt die entsprechende Karte. (In der App kann man sehen, das die Karte auch wirklich geändert wird...ggf. die App einmal neu starten)
Erzeugt ein reading "MapLoaded". Bei Erfolg ein "['ok']".
Da ich ein reading "ok" für FTUI benötige, habe ich noch das userReading "MapLoadedTxt" hinzugefügt. Hier bleibt dann nur noch das "ok" übrig.

Das laden der Karte geht sehr schnell (anders als in der App). Deswegen lade ich die Karte jedes Mal vor beginn der Reinigung.

Gruß
Bismosa
1x nanoCUL 433MHz (SlowRF Intertechno) für Fenstersensoren
1x nanoCUL 868Mhz für MAX (9x HT 1xWT)
1x ZigBee CUL
Weiteres: Squeezebox server, Kindle Display, ESP8266, Löterfahrung, ...

RappaSan

Seit neuestem haben wir zu Hause einen Roborock S7 MaxV Ultra in Betrieb.
Soweit alles gut bisher, aber ist es normal, daß die history_0 bis history_9 nicht mehr in den readings sind?

erdnar

... "normal" in so fern, dass es bei mir auch nicht auftaucht  :-\
ErdnaR

DeeSPe

Mein Roborock S7 wird automatisch anhand der Bewohneranwesenheit von FHEM gesteuert.
Das klappt auch soweit sehr gut.
Allerdings wird immer im "normalen" Modus "Alle" gereinigt. Ich habe mir eigentlich eine individuelle Raumreinigung zusammengestellt, bei der nur bestimmte Räume auch gewischt werden sollen. Wenn ich vor der automatischen Reinigung in der App auf "individuell" umstelle klappt das auch, nur ist die Einstellung nach jeder Reinigung wieder zurückgesetzt und bei der nächsten automatischen Reinigung wird wieder überall gewischt.
Wie kann ich denn über FHEM mitgeben dass er vor Beginn der Reinigung wieder auf "individuell" umstellt?

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

erdnar

Hallo Dan,
ich verstehe zwar deine Frage nicht richtig (z.B. habe ich keinen "normalen" Modus im Fhem), gebe aber mal meinen Senf dazu:
Meinen Sauger (ist als XiaomiDevice im Fhem) starte ich immer über DOIFs (egal ob über Anwesenheitserkennung (ganze Wohnung) oder per Zuruf, z.B. "Alexa starte Küche saugen"), die den gewünschten Modus einstellen:({fhem("
set MQ_GollumSchalter OFF;
sleep 2;
set MQ_GollumSchalter ON;
sleep 10;
set SaugerS7 reconnect;
sleep 10;
set SaugerS7 cleaning_mode turbo;
sleep 2;
set SaugerS7 zone Küche
")}

Wobei "MQ_GollumSchalter" in Verbindung mit "reconnect" den ggfs. tief schlafenden Sauger wachrütteln.
Wenn ich die Reinigung lediglich mit "set SaugerS7 start" aktiviere, nimmt er natürlich die gerade eingestellten Reinigungsparameter, wobei ich immer leicht feucht wischen lasse (so lange das Wasser reicht) und die Teppicherkennung aktiv habe.
ErdnaR

DeeSPe

Hey ErdnaR,

danke für Deinen Hilfeversuch.
Mit "normalem" Modus meinte ich den "Vac & Mop" Modus.
Eigentlich suchte ich eine Möglichkeit per FHEM zwischen "Vac & Mop", "Wischen", "Saugen" und "Individuell" umzuschalten, da ich alles auf "Individuell" eingerichtet habe und bis heute dachte dass der Roboter beim täglichen Start der Reinigung alleine wieder auf "Vac & Mop" zurückfällt.
Nach heutiger erneuter Analyse des Codes meiner DailyWork Funktion ist mir aber aufgefallen dass nach meinem Startbefehl noch "set cleaning_mode turbo" hinterher kam (Relikt von meinem S1). Und genau das war wohl das Problem. Sobald man den "cleaning_mode" umstellt wechselt der Roboter wieder auf "Vac & Mop". Nachdem ich das heute heraus gelöscht habe ist er brav im Modus "Individuell" gefahren und steht nach der Reinigung auch immer noch in diesem Modus.

Mein eigentliches Problem ist damit gelöst.
Schön wäre es aber trotzdem wenn man per FHEM die verschiedenen Modi umschalten könnte, denn eigentlich würde es mir reichen wenn der Roboter alle 2 Tage wischt und sonst nur saugt.

Gruß
Dan

P.S. Das mit dem Wachrütteln habe ich nicht ganz verstanden. Meiner reagiert eigentlich immer wenn ich ihn per FHEM anspreche, es sei denn er ist disconnected.
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

erdnar

Zitat von: DeeSPe am 05 Februar 2023, 20:26:13
P.S. Das mit dem Wachrütteln habe ich nicht ganz verstanden. Meiner reagiert eigentlich immer wenn ich ihn per FHEM anspreche, es sei denn er ist disconnected.

Genau dafür ist das. Der Gollumschalter schaltet die Ladestation aus/an, danach connected er meist wieder.
ErdnaR

DeeSPe

Ahhh, also ist Gollumschalter die schaltbare Steckdose für den S7!
Danke für die Erklärung.

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

gorefield

Moin,

seit kurzem werkelt ein Roborock S7 Pro Ultra in unserem Heim und mir fiel nach Einbindung in FHEM über das Modul 72_XiaomiDevice (wie auch schon anderen zuvor) auf, dass die Readings history_0-9 sowie last_clean_area|time und last_timestamp nicht da waren oder nicht gefüllt wurden.

Ein wenig Ursachenvorschung führte mich dann zu den JSON-Antworten des Bots, die anders strukturiert sind als vorherige Generationen. Mit ein wenig probieren und Trial and Error habe ich (eine mir) passende Version des Moduls geschrieben. Es ist ziemlich quick and dirty (zumal es mein erster Ausflug überhaupt in Perl ist), aber es funktioniert hier gut.

Die neuen Abfragen im Code sind auf das Model roborock.vacuum.a62 gemünzt, wie sich der S7 Pro Ultra hier meldet. Alles andere sollte unverändert weiter funktionieren.

Hier das Diff als Kurzform:

3449c3449,3450
<         return undef if(!defined($json->{result}));
---
>     return undef if(!defined($json->{result}));
>     return undef if(ref($json->{result}) ne "ARRAY");
3452,3465c3453,3455
<
<     if($hash->{model} eq "roborock.vacuum.a62") # Roborock S7 Pro Ultra
<     {
<       return undef if(ref($json->{result}) ne "HASH");
<       readingsBulkUpdate( $hash, "total_clean_time", sprintf("%.2f",int($json->{result}{clean_time})/3600), 1 ) if(defined($json->{result}{clean_time}));
<       readingsBulkUpdate( $hash, "total_clean_area", sprintf( "%.2f" ,int($json->{result}{clean_area})/1000000), 1 ) if(defined($json->{result}{clean_area}));
<       readingsBulkUpdate( $hash, "total_cleans", $json->{result}{clean_count}, 1 ) if(defined($json->{result}{clean_count}));
<     } else {
<       return undef if(ref($json->{result}) ne "ARRAY");
<       readingsBulkUpdate( $hash, "total_clean_time", sprintf("%.2f",int($json->{result}[0])/3600), 1 ) if(defined($json->{result}[0]));
<       readingsBulkUpdate( $hash, "total_clean_area", sprintf( "%.2f" ,int($json->{result}[1])/1000000), 1 ) if(defined($json->{result}[1]));
<       readingsBulkUpdate( $hash, "total_cleans", $json->{result}[2], 1 ) if(defined($json->{result}[2]));
<     }
<
---
>     readingsBulkUpdate( $hash, "total_clean_time", sprintf("%.2f",int($json->{result}[0])/3600), 1 ) if(defined($json->{result}[0]));
>     readingsBulkUpdate( $hash, "total_clean_area", sprintf( "%.2f" ,int($json->{result}[1])/1000000), 1 ) if(defined($json->{result}[1]));
>     readingsBulkUpdate( $hash, "total_cleans", $json->{result}[2], 1 ) if(defined($json->{result}[2]));
3468,3474d3457
<     my @records = ();
<     if($hash->{model} eq "roborock.vacuum.a62") # Roborock S7 Pro Ultra
<     {
<       @records = @{$json->{result}{records}};
<     } else {
<       @records = @{$json->{result}[3]};
<     }
3477c3460
<     foreach my $cleanrecord (@records) {
---
>     foreach my $cleanrecord (@{$json->{result}[3]}) {
3498a3482
>
3517a3502
>       my @cleanrecord = @{$cleanrecord};
3519,3532c3504,3506
<       if($hash->{model} eq "roborock.vacuum.a62") # Roborock S7 Pro Ultra
<       {
<         return undef if(ref($cleanrecord) ne "HASH");
<
<         readingsBulkUpdate( $hash, "last_timestamp", $cleanrecord->{begin}, 1 ) if($recordnumber == 0 && defined($json->{result}[0]));
<         readingsBulkUpdate( $hash, "history_".$recordnumber, FmtDateTime($cleanrecord->{begin}).": ".sprintf( "%.2f" ,int($cleanrecord->{area})/1000000)."m² in ".sprintf("%.2f",int($cleanrecord->{duration})/3600)."h, ".(($cleanrecord->{complete} eq "0")?"not finished":"finished cleaning"), 1 ) if($recordnumber < 10 && defined($json->{result}[0]));
<       } else {
<         return undef if(ref($cleanrecord) ne "ARRAY");
<
<         my @cleanrecord = @{$cleanrecord};
<         #Log3 $name, 2, "$name: $history $day $daynumber \n".Dumper($cleanrecord);
<         readingsBulkUpdate( $hash, "last_timestamp", $cleanrecord[0], 1 ) if($recordnumber == 0 && defined($json->{result}[0]));
<         readingsBulkUpdate( $hash, "history_".$recordnumber, FmtDateTime($cleanrecord[0]).": ".sprintf( "%.2f" ,int($cleanrecord[3])/1000000)."m² in ".sprintf("%.2f",int($cleanrecord[2])/3600)."h, ".(($cleanrecord[5] eq "0")?"not finished":"finished cleaning"), 1 ) if($recordnumber < 10 && defined($json->{result}[0]));
<       }
---
>       #Log3 $name, 2, "$name: $history $day $daynumber \n".Dumper($cleanrecord);
>       readingsBulkUpdate( $hash, "last_timestamp", $cleanrecord[0], 1 ) if($recordnumber == 0 && defined($json->{result}[0]));
>       readingsBulkUpdate( $hash, "history_".$recordnumber, FmtDateTime($cleanrecord[0]).": ".sprintf( "%.2f" ,int($cleanrecord[3])/1000000)."m² in ".sprintf("%.2f",int($cleanrecord[2])/3600)."h, ".(($cleanrecord[5] eq "0")?"not finished":"finished cleaning"), 1 ) if($recordnumber < 10 && defined($json->{result}[0]));
3535d3508
<


Ich hoffe, das hilft dem Einen oder Anderen weiter.

Viele Grüße
GF

erdnar

Zitat von: gorefield am 15 März 2023, 15:54:32Moin,

seit kurzem werkelt ein Roborock S7 Pro Ultra in unserem Heim und mir fiel nach Einbindung in FHEM über das Modul 72_XiaomiDevice (wie auch schon anderen zuvor) auf, dass die Readings history_0-9 sowie last_clean_area|time und last_timestamp nicht da waren oder nicht gefüllt wurden.

Ein wenig Ursachenvorschung führte mich dann zu den JSON-Antworten des Bots, die anders strukturiert sind als vorherige Generationen. Mit ein wenig probieren und Trial and Error habe ich (eine mir) passende Version des Moduls geschrieben. Es ist ziemlich quick and dirty (zumal es mein erster Ausflug überhaupt in Perl ist), aber es funktioniert hier gut.

Die neuen Abfragen im Code sind auf das Model roborock.vacuum.a62 gemünzt, wie sich der S7 Pro Ultra hier meldet. Alles andere sollte unverändert weiter funktionieren.

Hier das Diff als Kurzform:

------------ schnipp --- schnapp ------------

Ich hoffe, das hilft dem Einen oder Anderen weiter.

Viele Grüße
 GF

Hurra, wir haben einen neuem Maintainer für 72_XiaomiDevice
ok, Spass beiseite.  ;)
Ich habe leider keinen Durchblick mit Perl.
Könntest du evtl. den roborock.vacuum.a15 (das ist der einfachste S7) mit aufnehmen?
Danke
ErdnaR

gorefield

Zitat von: erdnar am 25 März 2023, 16:55:14Hurra, wir haben einen neuem Maintainer für 72_XiaomiDevice
Der war gut...  ;D

Zitat von: erdnar am 25 März 2023, 16:55:14Könntest du evtl. den roborock.vacuum.a15 (das ist der einfachste S7) mit aufnehmen?
Ist jetzt mit drin, analog zum S7 Pro Ultra, in der Annahme, dass sich beide gleich verhalten.

Aber Vorsicht: Das Einzige, was ich dazu testen konnte, ist, dass es bei mir nichts kaputt gemacht hat.  ;)

erdnar

Hallo Gorefield,
vielen Dank für die Änderung.
Es funktioniert auch mit meinem S7. Die history_*`s sind jetzt da und er funktioniert sogar noch. :))

Und wenn du wieder mal den Datenstrom deines S7 analysierst... die Handy-App erhält den Hinweis vom Robbi wenn das Wasser alle ist, Fhem leider (noch) nicht.

Danke und allen Frohe Ostern
ErdnaR

RappaSan

Hab's auch eingespielt - funktioniert so, wie es soll.
Danke dafür.

benedikt-wue

#2534
Hallo zusammen,
ich habe seit heute den Mi Vacuum - Mop 2, der mit dem Modul auch in FHEM erkannt wird und "connected" ist (Token stimmt also), leider zeigt er mir nur vier Readings an:

device_firmware
4.3.3_1026
2023-04-14 14:02:14
device_uptime
0.31
2023-04-14 14:02:14
error
useracktimeout
2023-04-14 15:08:41
state
connected
2023-04-14 13:48:29
wifi_rssi
-50
2023-04-14 14:02:14

Bei meinem "alten" Vacuum hat alles funktioniert und FHEM hat mir alle möglichen Readings angezeigt, die ich dann schön in der FTUI habe anzeigen lassen und ich würde mir sehr wünschen, dass das wieder so ist :-)
Ebenso funnktioniert auch kein set - Befehl, bzw. reagiert das Putzflittchen nicht :-)
Besonders stutzig macht mich der "error useracktimeout"... Vielleicht hat jemand das gleiche Gerät und könnte mir weiterhelfen?
attr VacuumCleaner ist übrigens auch gesetzt ;-)
Jemand bereit und "fähig", das Problem zu lösen?

edit: in meiner FHEM - Installation wird das Teil wohl als "dreame.vacuum.p2140p" erkannt... auf einer anderen Seite (valetudo) habe ich noch gefunden, dass es evtl. auch als Xiaomi 1C bezeichnet werden kann (wobei ich mir da nicht ganz sicher bin, da ich Mi Vacuum Mop 2 habe und nicht ohne die Ziffer am Ende... evtl. hilft das bei einer möglichen Problemlösung weiter?