NEWS
Datenpunkte im Objekte-Baum verschieben
-
Hallo Zusammen!
Ich würde gerne mal etwas in meinen "Eingenen Datenpunkten" aufräumen und eine bessere Struktur erzeugen.
So würde ich gerne alle Datenpunkte "Bewegung..." in einen Unterordner packen.
Leider finde ich keine Option Datenpunkte zu verschieben, also z.B. in Unterordner.
Nur löschen und neu erzeugen ist halt viel mehr Arbeit als einfach zu verschieben...Gruß
Tobias -
@fibricus Da bleibt Dir nichts Anderes, als die Datenpunkte neu zu erstellen und dann die alten zu löschen. U(nd dran denken, dass Du auch jedes Script, welches auf die (alten) Datenpunkte zugreift, sowie sämtliche Views in VIS(2) auf die neuen Datenpunkte anpassen musst.
Einen Teil Deiner Datenpunkte könntest Du möglicherweise auch unter alias.0 erzeugen, dann kannst Du sie ohne Script direkt mit dem jeweiligen originalen Datenpunkt „verknüpfen“, was den möglicherweise mal nötigen Austausch von Geräten erleichtert, da dann nur der ALIAS neu verknüpft werden muss, während Scripte und Views, die auf den ALIAS zeigen unverändert bleiben können.Gruss, Jürgen
-
@fibricus so direkt geht das nicht, aber ...
Dann wird der Objektbaum den du gerade markiert hast exportiert.
Die Datei ist eine "schnöde" Textdatei die du in einem Editor deiner Wahl bearbeiten kannst:
Der Editor deiner Wahl ist übrigens NICHT Notepad sondern so etwas wie Notepad++ da dieser den richtigen Zeichensatz und wie mit den Neue-Zeile-Zeichen umgegangen wird richtig erhält.Dort könntest du per Suchen und Ersetzen den Pfad ändern. In meinen Bildern könnte ich also alle
0_userdata.0.000-Testen.
durch0_userdata.0.Ein_neuer_Pfad.ist.hier.
ersetzen.
Dann Speichern und in der Objektansicht wieder importieren.Danach kannst du den alten Zweig ja löschen.
In der Textdatei könntest du Datenpunkte die du nicht drin haben willst löschen. Was nun mühsamer / aufwendiger ist musst du selbst entscheiden.
Tipp für die Zukunft: Meine Skripts haben als Anfang immer das erstellen der Datenpunkte, dazu gibt es entsprechende Blöcke in Blockly und Befehle in JavaScript. Ich setze immer eine Variable als Stammpfad und ausgehend von der lasse ich alle anderen Datenpunkte im Skript anlegen und verwende diese.
So kann ich wenn ich den Pfad ändern will (oder eine 2. Version des Skriptes laufen will) das einmal am Kopf ändern und der Rest passiert von alleine -
@bananajoe said in Datenpunkte im Objekte-Baum verschieben:
Tipp für die Zukunft: Meine Skripts haben als Anfang immer das erstellen der Datenpunkte, dazu gibt es entsprechende Blöcke in Blockly und Befehle in JavaScript. Ich setze immer eine Variable als Stammpfad und ausgehend von der lasse ich alle anderen Datenpunkte im Skript anlegen und verwende diese.
So kann ich wenn ich den Pfad ändern will (oder eine 2. Version des Skriptes laufen will) das einmal am Kopf ändern und der Rest passiert von alleineDas hört sich toll an, aber ich verstehe das leider nichtwirklich.
Hättest Du mal ein kleines Beispiel? -
Es geht auch mit Kopieren
Auf bearbeiten klicken (Stift) dann unten links auf kopieren
namen enden und auf klonen klicken -
@wildbill said in Datenpunkte im Objekte-Baum verschieben:
@fibricus Da bleibt Dir nichts Anderes, als die Datenpunkte neu zu erstellen und dann die alten zu löschen. U(nd dran denken, dass Du auch jedes Script, welches auf die (alten) Datenpunkte zugreift, sowie sämtliche Views in VIS(2) auf die neuen Datenpunkte anpassen musst.
Einen Teil Deiner Datenpunkte könntest Du möglicherweise auch unter alias.0 erzeugen, dann kannst Du sie ohne Script direkt mit dem jeweiligen originalen Datenpunkt „verknüpfen“, was den möglicherweise mal nötigen Austausch von Geräten erleichtert, da dann nur der ALIAS neu verknüpft werden muss, während Scripte und Views, die auf den ALIAS zeigen unverändert bleiben können.Gruss, Jürgen
Leider habe ich das mit den Aliassen zu spät verstanden.
Ich muss mich mal daran machen und alle Scripte umzuschreiben.
Leider habe ich noch keine gute Idee für die Sortierung und daher drücke ich mich im Moment noch vor der Arbeit.
Und ich fürchte es gibt auch keine Patentlösung für die Sortierung, oder. -
-
Hier schon mal Blockly:
In der aktuellen Version (Beta Channel) gibt es 2 Blöcke dafür:
Der erste Block ist flexibler, aber umständlicher.
Beispiel für eine Prozent-Zahl:
Im grünen Textfeld steht folgendes:{ "type": "number", "name": "MeinWert", "read": true, "write": true , "unit" : "%" }
und so sieht der Datenpunkt dazu aus der erzeugt wird:
Etwas umständlich, aber über das
Common
Feld kann man halt alle Aspekte einstellen.
Einfacher ist da der andere Block:
Den Zustandstyp wählt man einfach aus, setzt die Haken und den Init-Wert:
Nachteil beim 2. ist das du keine Einheit setzen kannst (wobei das ja nur für die Optik ist, ich finde das aber schön wenn da gleich W, kWh oder % dran steht)
Beide Blöcke haben das Problem das man beim Namen des Datenpunktes nicht mit Variablen arbeiten kann.
Ich arbeite gerne mit Blockly und habe mir deshalb einen passenden Skript-Baustein dafür erstellt:
Importdaten kommen untenBeispielaufrufe:
Damit kann ich mir meine Datenpunkte bauen. Wenn man kann Unit will / sinnvoll ist einfach nur ein leeres Textfeld draufziehen.Hier alle Beispiele zum Importieren inklusive meiner Funktion:
<xml xmlns="https://developers.google.com/blockly/xml"> <variables> <variable id=",%o6YJ)eJJ0Ug#A.g^(q">RootPath</variable> <variable id="4,_+,~ymq5aD:jd.9$=-">ValueName</variable> <variable id="!-(EoW{]I%^4o]}Wf0IU">TargetType</variable> <variable id="2NeMF,lRvUfhS/0US`~(">TargetIsWriteable</variable> <variable id="pEXy5(i!?xF*I2u|UIbk">TargetUnit</variable> <variable id="oS^boSLi7Wy4dN^qi{ek">TargetDefaultValue</variable> <variable id="6#H4rASkoUt5zIIwARJ;">Stammpfad</variable> </variables> <block type="procedures_defcustomnoreturn" id="l(.(|wVZ(GS{-P%@qK=|" x="113" y="-87"> <mutation statements="false"> <arg name="RootPath" varid=",%o6YJ)eJJ0Ug#A.g^(q"></arg> <arg name="ValueName" varid="4,_+,~ymq5aD:jd.9$=-"></arg> <arg name="TargetType" varid="!-(EoW{]I%^4o]}Wf0IU"></arg> <arg name="TargetIsWriteable" varid="2NeMF,lRvUfhS/0US`~("></arg> <arg name="TargetUnit" varid="pEXy5(i!?xF*I2u|UIbk"></arg> <arg name="TargetDefaultValue" varid="oS^boSLi7Wy4dN^qi{ek"></arg> </mutation> <field name="NAME">CreatyMyStateV3</field> <field name="SCRIPT">aWYgKFRhcmdldFVuaXQubGVuZ3RoID09PSAwKSB7DQogICAgYXdhaXQgY3JlYXRlU3RhdGVBc3luYyhSb290UGF0aCArIFZhbHVlTmFtZSwgVGFyZ2V0RGVmYXVsdFZhbHVlLCB7IHR5cGU6IFRhcmdldFR5cGUsIG5hbWU6IFZhbHVlTmFtZSwgcmVhZDogdHJ1ZSwgd3JpdGU6IFRhcmdldElzV3JpdGVhYmxlIH0pOw0KfSBlbHNlIHsNCiAgICBhd2FpdCBjcmVhdGVTdGF0ZUFzeW5jKFJvb3RQYXRoICsgVmFsdWVOYW1lLCBUYXJnZXREZWZhdWx0VmFsdWUsIHsgdHlwZTogVGFyZ2V0VHlwZSwgbmFtZTogVmFsdWVOYW1lLCByZWFkOiB0cnVlLCB3cml0ZTogVGFyZ2V0SXNXcml0ZWFibGUgLCB1bml0OiBUYXJnZXRVbml0IH0pOw0KfQ==</field> <comment pinned="false" h="80" w="160">Beschreibe diese Funktion …</comment> </block> <block type="comment" id="}(ktD4g-)QZZ@xfCwW7h" x="112" y="-37"> <field name="COMMENT">Stammpfad mit . am Ende</field> <next> <block type="variables_set" id="l}h_T.]F;0S)D1{H|KSg"> <field name="VAR" id="6#H4rASkoUt5zIIwARJ;">Stammpfad</field> <value name="VALUE"> <block type="text" id="o`+2zY{=f_]hiviefh`g"> <field name="TEXT">0_userdata.0.000-Testen.</field> </block> </value> <next> <block type="comment" id="d#Ob/)kWuaO?W6ub$MU]"> <field name="COMMENT">Boolean</field> <next> <block type="procedures_callcustomnoreturn" id="$ilXQQ6kXQ7Fk)B9HoI+"> <mutation name="CreatyMyStateV3"> <arg name="RootPath"></arg> <arg name="ValueName"></arg> <arg name="TargetType"></arg> <arg name="TargetIsWriteable"></arg> <arg name="TargetUnit"></arg> <arg name="TargetDefaultValue"></arg> </mutation> <value name="ARG0"> <block type="variables_get" id="@tbS0:e$Br]KyQ,LDLQ)"> <field name="VAR" id="6#H4rASkoUt5zIIwARJ;">Stammpfad</field> </block> </value> <value name="ARG1"> <block type="text" id="Nnx1nIC6!|i=ogk/5l#V"> <field name="TEXT">Mein_Test_Boolean</field> </block> </value> <value name="ARG2"> <block type="text" id="L5ulp_swl_c@^WXuRt$]"> <field name="TEXT">boolean</field> </block> </value> <value name="ARG3"> <block type="logic_boolean" id="wkUbqDv{k1SA(__`([cc"> <field name="BOOL">TRUE</field> </block> </value> <value name="ARG4"> <block type="text" id="}JGSQW)pe7%!];~aDG-W"> <field name="TEXT"></field> </block> </value> <value name="ARG5"> <block type="logic_boolean" id="%:^.D{FIyHk4cMis|Q4b"> <field name="BOOL">FALSE</field> </block> </value> <next> <block type="comment" id="xS03/Vf|O#tR*siuUQ{5"> <field name="COMMENT">kWh</field> <next> <block type="procedures_callcustomnoreturn" id="c[Sy+wM8GeeL2=vrt:hy"> <mutation name="CreatyMyStateV3"> <arg name="RootPath"></arg> <arg name="ValueName"></arg> <arg name="TargetType"></arg> <arg name="TargetIsWriteable"></arg> <arg name="TargetUnit"></arg> <arg name="TargetDefaultValue"></arg> </mutation> <value name="ARG0"> <block type="variables_get" id="@QkZl7LqofYBl`EMr,Dx"> <field name="VAR" id="6#H4rASkoUt5zIIwARJ;">Stammpfad</field> </block> </value> <value name="ARG1"> <block type="text" id="VAJ;l;/[j~zPvYm/QqId"> <field name="TEXT">Mein_Test_kWh</field> </block> </value> <value name="ARG2"> <block type="text" id="EEsLej~G+k:#U~n5xxY6"> <field name="TEXT">number</field> </block> </value> <value name="ARG3"> <block type="logic_boolean" id="IUTW[TQ1=czdK/zsGybc"> <field name="BOOL">TRUE</field> </block> </value> <value name="ARG4"> <block type="text" id="u%*q8d$3n[zEMWfQ%w(0"> <field name="TEXT">kWh</field> </block> </value> <value name="ARG5"> <block type="math_number" id="~D.kzZ/Ty)TFH7C^|3CE"> <field name="NUM">72</field> </block> </value> <next> <block type="comment" id="DJ;J_wTj#zl}dM,3_|ns"> <field name="COMMENT">% Zahl</field> <next> <block type="procedures_callcustomnoreturn" id="IroeW5.+4(SnlFjhg@@*"> <mutation name="CreatyMyStateV3"> <arg name="RootPath"></arg> <arg name="ValueName"></arg> <arg name="TargetType"></arg> <arg name="TargetIsWriteable"></arg> <arg name="TargetUnit"></arg> <arg name="TargetDefaultValue"></arg> </mutation> <value name="ARG0"> <block type="variables_get" id="MA$JYk3c8]a5*Hu*)u8B"> <field name="VAR" id="6#H4rASkoUt5zIIwARJ;">Stammpfad</field> </block> </value> <value name="ARG1"> <block type="text" id="g:k+~9!bew$*)3IPU59`"> <field name="TEXT">Mein_Test_Prozent</field> </block> </value> <value name="ARG2"> <block type="text" id="YD!!HrbK`%i}U/]{21-#"> <field name="TEXT">number</field> </block> </value> <value name="ARG3"> <block type="logic_boolean" id="94ekT=!c%}2yK{lZ02{T"> <field name="BOOL">TRUE</field> </block> </value> <value name="ARG4"> <block type="text" id="*=LQ{FyLM}I/s|xLO^_I"> <field name="TEXT">%</field> </block> </value> <value name="ARG5"> <block type="math_number" id="bcN2aoW4bI1:Y~`uzSM0"> <field name="NUM">72</field> </block> </value> </block> </next> </block> </next> </block> </next> </block> </next> </block> </next> </block> </next> </block> </next> </block> <block type="create" id="IQ;+nwEO/Ugu#pu0-4%g" x="113" y="688"> <field name="NAME">0_userdata.0.000-Testen.MeinWert_Prozent</field> <value name="VALUE"> <block type="math_number" id="aig):o)b^kV85oVK(/yL"> <field name="NUM">0</field> </block> </value> <value name="COMMON"> <block type="text" id="G~lppP6eh58MqL5/@EMZ"> <field name="TEXT">{ "type": "number", "name": "MeinWert", "read": true, "write": true , "unit" : "%" }</field> </block> </value> <next> <block type="create_ex" id="~Qn#,B?tGP62!{Q~CaMp"> <field name="NAME">0_userdata.0.000-Testen.MeinWert_Boolean</field> <field name="TYPE">boolean</field> <field name="READABLE">TRUE</field> <field name="WRITEABLE">TRUE</field> <value name="VALUE"> <block type="logic_boolean" id="%a^I]Fd;o,H2sQnL=%ee"> <field name="BOOL">TRUE</field> </block> </value> </block> </next> </block> </xml>
In allen Fällen werden die Datenpunkte so erzeugt das man diese danach sofort verwenden kann.
Später / weiter unten im Skript nutze ich die Datenpunkte immer per Textfelder:
Will ich die Pfade ändern bzw. eine weitere version meines Skriptes laufen lassen aber mit anderen Datenpunkten muss ich nur oben die Variable
Stammpfad
ändern und die anderen Datenpunkte landen an eben diesen neuen Pfad.
Das mach ich mit allen Objekten, also auch mit Zigbee-Sensoren. da speichere ich mir den Pfad zum Objekt auch in einer Variablen und nutze unten nach dem gleichen Schema diese Variable statt des Datenpunktes. Wie du siehst kann man überall auch Textfelder draufziehen wo er eigentlich ein Dialogfeld für die Auswahl anbietet.
Durch das zusammenbauen kann ich den Pfad zum ZigBee-Sensor angeben:
zigbee.0.00158d00044c0e6b
und hänge dann an was genau ich haben will pererstelle Text aus
, also zum Beispiel.temperature
oder.humidity
Zum einen finde ich das lesbarer, zum anderen kann das so auch in eigene Funktionen packen die ich dann mit dem Pfad des jeweiligen Sensors aufrufe - du kanns ka auch aus Blockly-Bausteinen Funktionen bauen. -
@pajda War mir gar nicht bekannt. Ändert aber auch nicht viel an der Handarbeit und dem nachträglichen manuellen Anpassen von Scripten und VIS. Aber Danke.
Gruss, Jürgen
-
@bananajoe WOW - das werde ich wohl ein paar mal lesen und mit spielen müssen, bis ich (als Anfänger) das verstehe.
Vielen Dank für dieses ausführliche Posting!
Genau dafür liebe ich solche Foren... -
@fibricus ich hätte auch noch - bei Bedarf - eine pure JavaScript Variante. Eigentlich ist das nur ein Befehl, ich habe mir (mit Hilfe dieses Forums) aber ebenfalls das als Funktion gebaut damit man die Datenpunkte unmittelbar nach dem erstellen Verwenden kann. Der bedarf besteht zwar in der Regel nur beim allerersten Start, aber auch dann soll ja gleich alles ordentlich laufen.
Das müsste ich dann aber noch mal vorher "schön" machen
-
Moin, mich würde das definitiv interessieren.
Meinst du sowas in der Art:
Name = dp_value; Path = path; const obj = { type: 'state', name: Name, native: {}, "common": { "name": Name, "desc": "Von Blockly erzeugt", "role": "value", "type": "number", "read": true, "write": true, "def": 0, } } if(!existsObject(Path + "." + Name)) { setObject(Path + "." + Name, obj); return 1; }else{ return 0; }
Das ist ja nur die Funktion mit Pfad und Name. Wenn du da etwas schöneres hast, dann immer her damit.
Gruß, Johannes
-
@jojo58 Der Trick ist das die Erstellung in eine Async-Funktion gesteckt werden muss.
Ich habe mal aus einem meiner vorhandenen Skripte das ordentlich zusammengekürzt:// Setup var s_DeviceName = "HC-SR04-01"; // Suffix wird an den Devicenamen für die Zieldatenpunkte angehängt, z.B. "-Waschmaschine" (KEINE Punkte!!!) var s_Suffix = "-Regenwassergrube"; // Festlegen der Skriptversion (für Auswertungen) var s_VersionJSScript = "1.20" // Datenpunktstammpfad var s_state_rootpath = "0_userdata.0.000-Testen.tasmota."; var s_state_FullPath = s_state_rootpath + s_DeviceName + s_Suffix; // Benötigte Datenpunkte erstellen async function CreateMyStatesAndStartup() { try { // ####################################################################################################### // POWER await createStateAsync(s_state_FullPath + ".POWER", false, { type: 'boolean', read: true, write: true, role: "switch", name: s_DeviceName + s_Suffix + '.POWER' }); // ####################################################################################################### // Version-JS-Script await createStateAsync(s_state_FullPath + ".Version-JS-Script", s_VersionJSScript, { type: 'string', read: true, write: false, name: 'Version-JS-Script' }); // ####################################################################################################### // Version-JS-Script-Path await createStateAsync(s_state_FullPath + ".Version-JS-Script-Path", scriptName, { type: 'string', read: true, write: false, name: 'Name und Pfad des Skriptes' }); } catch (error) { console.warn(error); log(error); } } // Zielpunkte anlegen falls noch nicht vorhanden // Das erstellen machen wir in einer async Funktion CreateMyStatesAndStartup(); // Hier der Rest deines Skriptes, alle obigen Datenpunkte sind nun nutzbar
Die ersten Zeilen legen den Gerätenamen fest (Setup). Grund ist das ich bei Updates des Skriptes den ganzen Rest darunter einfach überschreibe (das stammt aus einem Skript was für jedes einzelne Tasmota-Gerät bei mir einmal läuft)
Es folgt der Abschnitt Variablen in welchen ich den Stammpfad festlege.
Dann die Funktion
CreateMyStatesAndStartup
welche die Datenpunkte bei Aufruf anlegt....AndStartup
weil ich darin noch ein paar andere Dinge tue. Schon innerhalb der Funktion kann man die Datenpunkte dann sofort nutzen. Ich erstelle die alle und hole mir dann schon ein paar Grundwerte und trage die ein.Den Abschnitt Datenpunkte - der ist noch historisch. Da stand mal alles drin was nun in der Funktion ist. Diese wird dort einfach nur aufgerufen
Dann kommen die Subscription - also die ganzen Trigger die dann entsprechend reagieren.
Das mit den Bannern im Quelltext ist so ein Spleen von mir, das mach schon seit Jahrzehnten so um in Skripten / Programmen dinge schneller wiederzufinden bzw. zu Ordnen (ich habe nicht immer eine richtige Entwicklungsumgebung)
Nachtrag: Keine Ahnung wo die ganzen
{1}
herkommen, beim reinkopieren sind die noch nicht da, ich schau mal ob ich diese weg bekommeNachtrag 2: er mochte die Banner nicht, die habe ich nun gelöscht
-
Danke dir, werde mich mal damit beschäftigen. Übrigens, mit den Bannern, das hatte schon was
erinnerte mich an früher, als es noch so Info Dateien zu kleinen Programmen hab.