Hallo!
Ich habe mir bereits einen Wolf gesucht und bin offensichtlich noch immer nicht auf die richtige Lösung gestoßen:
Ich habe einen Saugroboter mit Valetudo (nicht RE), welcher über MQTT seine Räume mit Nummerierung meldet.
Nun möchte ich über ein Widget ,,multiple-strict" die Auswahl der zu saugenden Räume ermöglichen.
Ich fände es jetzt nur unschön, im Widget lediglich die Zahlen zur Auswahl angezeigt zu bekommen, da der WAF damit sehr überschaubar ist.
Stattdessen stelle ich mir vor, dass das Widget die Möglichkeit bietet, einen Wert anzuzeigen und einen anderen zu übermitteln (HTML bietet ja diese Möglichkeit im option-Tag).
Kann ich einem multiple-strict (oder notfalls einem select-strict) für jeden kommaseparierten Eintrag ein Value mitgeben oder müssen Value und angezeigter Text zwingend immer nur ein- und dasselbe sein?
Kann eine eventMap eventuell die Lösung sein?
Gruß Marco
Interessant knoble ich gerne mit :), auch wenn ich Valetudo RE nutze.
Zeigst du mal ein List von dem Sauger bitte.
Gruß
Thomas
ZitatKann eine eventMap eventuell die Lösung sein?
Ja.
In Ordnung, wenn es mit einer eventMap geht, mach ich an der Stelle mal weiter. Dass ich da einen JSON-String basteln muss, macht es nicht leichter, aber damit hab ich schonmal nen Ansatzpunkt.
Das Gerät sieht wie folgt aus:
Internals:
DEVICETOPIC DreameZ10Pro
FUUID 61b26afa-f33f-269a-74a1-26451dde6923aa72
IODev myBroker
LASTInputDev myBroker
MSGCNT 154421
NAME UG_DreameZ10Pro
NR 149
STATE clean_segment
TYPE MQTT2_DEVICE
myBroker_MSGCNT 154421
myBroker_TIME 2021-12-27 16:05:06
OLDREADINGS:
READINGS:
2021-12-27 16:05:05 1 Flur
2021-12-27 16:05:05 2 Vorratskammer
2021-12-27 16:05:05 3 Esszimmer
2021-12-27 16:05:05 4 Küche
2021-12-27 16:05:05 5 Bad
2021-12-24 15:46:16 IODev myBroker
2021-12-27 16:05:06 attachment_dustbin true
2021-12-27 16:05:06 attachment_mop false
2021-12-27 16:05:06 attachment_watertank false
2021-12-27 16:05:06 battery_level 91
2021-12-27 16:05:06 battery_status none
2021-12-27 16:05:06 consumable_brushmain 1065600
2021-12-27 16:05:06 consumable_brushside 705600
2021-12-27 16:05:06 consumable_filtermain 525600
2021-12-27 16:05:06 consumable_sensorall 93600
2021-12-27 16:05:06 fanspeed_preset medium
2021-12-27 13:45:20 state clean_segment
2021-12-27 16:05:06 state_detail none
2021-12-27 16:05:06 state_status docked
2021-12-27 16:05:06 statistics_area 80000
2021-12-27 16:05:06 statistics_time 660
2021-12-27 16:05:06 waterusage_preset medium
2021-12-27 16:05:06 wifi_frequency 2.4ghz
2021-12-27 16:05:06 wifi_ips <redacted>
2021-12-27 16:05:06 wifi_signal -58
2021-12-27 16:05:06 wifi_ssid <redacted>
Attributes:
IODev myBroker
alias Staubsauger UG
cmdIcon start:remotecontrol/black_btn_PLAYgreen stop:remotecontrol/black_btn_POWEROFF3 charge:electric_car_icon
devStateIcon {my $batt = ReadingsVal($name,"battery_level",0); my $onl = $batt >= 80 ? "tablet_bat_100" : $batt >= 50 ? "tablet_bat_66" : $batt >= 20 ? "tablet_bat_33" : "tablet_bat_0"; my $ip = (split ",",ReadingsVal($name,"wifi_ips",""))[0]; "<div><a target=\"blank\" href=\"http://".$ip."\">".
FW_makeImage($onl)."</a></div>"}
devicetopic DreameZ10Pro
event-on-change-reading .*
group Staubsauger
icon vacuum_top
readingList UG/DreameZ10Pro/BatteryStateAttribute/level:.* battery_level
UG/DreameZ10Pro/BatteryStateAttribute/status:.* battery_status
UG/DreameZ10Pro/StatusStateAttribute/status:.* state_status
UG/DreameZ10Pro/StatusStateAttribute/detail:.* state_detail
UG/DreameZ10Pro/AttachmentStateAttribute/dustbin:.* attachment_dustbin
UG/DreameZ10Pro/AttachmentStateAttribute/watertank:.* attachment_watertank
UG/DreameZ10Pro/AttachmentStateAttribute/mop:.* attachment_mop
UG/DreameZ10Pro/ConsumableMonitoringCapability/brush-main:.* consumable_brushmain
UG/DreameZ10Pro/ConsumableMonitoringCapability/brush-side_right:.* consumable_brushside
UG/DreameZ10Pro/ConsumableMonitoringCapability/filter-main:.* consumable_filtermain
UG/DreameZ10Pro/ConsumableMonitoringCapability/sensor-all:.* consumable_sensorall
UG/DreameZ10Pro/CurrentStatisticsCapability/time:.* statistics_time
UG/DreameZ10Pro/CurrentStatisticsCapability/area:.* statistics_area
UG/DreameZ10Pro/WaterUsageControlCapability/preset:.* waterusage_preset
UG/DreameZ10Pro/FanSpeedControlCapability/preset:.* fanspeed_preset
UG/DreameZ10Pro/WifiConfigurationCapability/ssid:.* wifi_ssid
UG/DreameZ10Pro/WifiConfigurationCapability/ips:.* wifi_ips
UG/DreameZ10Pro/WifiConfigurationCapability/frequency:.* wifi_frequency
UG/DreameZ10Pro/WifiConfigurationCapability/signal:.* wifi_signal
UG/DreameZ10Pro/MapData/segments:.* { json2nameValue($EVENT); }
setList start:noArg UG/DreameZ10Pro/BasicControlCapability/operation/set START
stop:noArg UG/DreameZ10Pro/BasicControlCapability/operation/set STOP
charge:noArg UG/DreameZ10Pro/BasicControlCapability/operation/set HOME
clean_segment:{"multiple-strict,1,2,3,4,5"} { my @segments = split(',', $EVTPART1); my $json_str = encode_json(\@segments); return 'UG/DreameZ10Pro/MapSegmentationCapability/clean/set { "segment_ids": '.$json_str.', "iterations": 1, "customOrder": true }'; }
webCmd charge:clean_segment
Meine spontane Idee dazu, weil ich mich letzte Woche gerade damit beschäftigt habe:
Mit eventMap den Zonen-settern einen Präfix geben (beispielhaft EG_.*|OG.*), die Liste aller setternamen auslesen und nach den Präfixen filtern und in einem userReadings kommasepariert, zum auslesen in dem multiple-strict, festhalten:
attr UG_DreameZ10Pro userReadings <cmndsname>:<trigger> {my @u=map {(split ':',$_)[0]} split '\s',getAllSets($name);my @z;for (@u) {$_ =~ 'EG.*|OG.*' ? push @z,$_ : next}; return join ',',@z; }
Im Widget:
<cmndname>:{'multiple-strict,'.ReadingsVal($name,'<cmndsname>','none');} {}
edit:
mir kommt gerade, für dich völlig nutzlos, du gibst die setter einfach im Widget an und gut ist.
Idealerweise hätte ich halt gern die kommaseparierte Liste des Widgets anhand der übergebenen Segmente bei jedem Roboter dynamisch erzeugt, da könnte dein Code aber ein Ansatzpunkt sein.
Und über die eventMap komme ich sicherlich dahin, dass mir das Widget die Nummern statt der Segment-Namen gibt.
Den JSON-String werd ich dann wahrscheinlich in der myUtils bauen lassen.
Da werde ich glaub nochmal nen Abend investieren. :-)
Wechsel zu ValetudoRE ;D , da hab ich genau das was du jetzt mit Valetudo vorhast die Tage dynamisch umgesetzt.
https://forum.fhem.de/index.php/topic,121017.msg1195353.html#msg1195353 (https://forum.fhem.de/index.php/topic,121017.msg1195353.html#msg1195353)
edit:
Ok, nicht genau das was du vorhast, aber fast, es müsste nur der "Ausführungsteil" angepasst werden.
edit2:
ZitatUnd über die eventMap komme ich sicherlich dahin, dass mir das Widget die Nummern statt der Segment-Namen gibt.
Sobald eventMap ins Spiel kommt kann das nicht mehr dynamisch sein (ohne rotes Fragezeichen).
Es wird auch ohne gehen :P, ich muss noch grübeln.
Ja, deinen verlinkten Beitrag habe ich auch schon gesehen. Aber ValetudoRE kommt für mich nicht in Frage. Schon gar nicht, seit MQTT in Valetudo komplett überarbeitet wurde.
Durch Wildcards in der eventMap wird sich da schon was dynamisch machen lassen. Zur Not muss die Frau halt die Weboberflächen der Roboter nutzen. :-D
Zitat von: rudolfkoenig am 27 Dezember 2021, 15:13:40
Ja.
@rudolphkoenig, kann es sein, dass die eventMap nur einmal angewandt wird? Der jeweils erste Wert aus dem Multiple wird gemappt, die danach nicht mehr. :o
Ansonsten klappt nun zumindest schonmal die Anzeige der Räume, geparst aus dem Reading:
UG/DreameZ10Pro/MapData/segments:.* json_segments
userReadings segments { my $segments = join(',', map {(split ':',$_)[1]} split ',',ReadingsVal($name,"json_segments","")); $segments =~ tr/{"}//d; return $segments; }
Danke für den Codeschnipsel, @TomLee
Zitat@rudolphkoenig, kann es sein, dass die eventMap nur einmal angewandt wird?
Ja, das habe ich wohl uebersehen, eventMap ist damit fuer dieses Problem ungeeignet.
Es sei denn, man moechte alle Moeglichkeiten einzeln aufzaehlen, bei 5 Raeumen sind es ja "nur" 32 :)
Ich wuerde das Mapping im setList und im readingList durchfuehren, mit zwei Funktionen im 99_myUtils.pm
Gut, dass ich ein Stockwerk mit 7 Segmenten hab. ;D
Die Idee mit dem Mapping im SetList hatte ich auch, dann mach ich an der Stelle mal weiter. Da ich derzeit aber ohnehin über eine Backup-/Restore-Funktion für die Karten nachdenke, um bei fehlgeschlagener Positionierung nicht wieder von vorn anfangen zu müssen, bin ich am Hadern, ob ich die Räume nicht einfach hardcode. Aber ne nette Knobelaufgabe ist es ja dennoch.
Lösung zu Dokumentationszwecken:
Gerät:
UG/DreameZ10Pro/MapData/segments:.* json_segments
setList stop:noArg UG/DreameZ10Pro/BasicControlCapability/operation/set STOP
charge:noArg UG/DreameZ10Pro/BasicControlCapability/operation/set HOME
clean_segment:{"multiple-strict,".getSegmentListFromJSON(ReadingsVal($name,"json_segments",""))} { return 'UG/DreameZ10Pro/MapSegmentationCapability/clean/set { "segment_ids": '.getIdsFromSegments($NAME,$EVTPART1).', "iterations": 1, "customOrder": true }'; }
webCmd clean_segment:stop:charge
webCmdLabel Zonen-Reinigung:Stop:Laden
99_myUtils.pm:
sub
getSegmentListFromJSON($)
{
my ($json) = @_;
my $segments = join(',', map {(split ':',$_)[1]} (split ',',$json));
$segments =~ tr/{"}//d;
return $segments;
}
sub
getIdsFromSegments($$)
{
my ($robot, $segmentset) = @_;
my $json_segments = ReadingsVal($robot,"json_segments","");
$json_segments =~ tr/{"}//d;
my %all_segments;
map {
my @entry = (split ':',$_);
$all_segments{$entry[1]} = $entry[0];
} (split ',',$json_segments);
my @checked_segments = (split ',', $segmentset);
my @checked_ids;
foreach(@checked_segments) {
push(@checked_ids,$all_segments{$_});
}
return encode_json(\@checked_ids);
}
1;
Verbesserungsvorschläge, vor allem am Array- und Hash-Gefrickel der unteren Methode, sind natürlich gerne gesehen.