Definition von value in den Select-/Multiple-Widgets

Begonnen von ph0x, 27 Dezember 2021, 14:52:40

Vorheriges Thema - Nächstes Thema

ph0x

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

TomLee

Interessant knoble ich gerne mit  :), auch wenn ich Valetudo RE nutze.

Zeigst du mal ein List von dem Sauger bitte.

Gruß

Thomas

rudolfkoenig

ZitatKann eine eventMap eventuell die Lösung sein?
Ja.

ph0x

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

TomLee

#4
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.

ph0x

#5
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. :-)

TomLee

#6
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

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.

ph0x

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

ph0x

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

rudolfkoenig

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

ph0x

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.

ph0x

#11
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.