Was zum Henker - if auf Contains, Find... funktioniert nicht

Homematic-, TCL- und Shell-Script, Toolchain, C, etc.

Moderator: Co-Administratoren

ACX_Com
Beiträge: 12
Registriert: 09.07.2022, 09:52
System: CCU

Was zum Henker - if auf Contains, Find... funktioniert nicht

Beitrag von ACX_Com » 01.05.2024, 10:48

UPDATE...
Zu unterem Thema habe ich jetzt herausgefunden, dass es an der Formatierung des .name() liegen muss.
Ersetze ich die Variable für device.name() testweise durch eine Zeichenkette...
string o_geraet = "Ping:3";
...so funktioniert alles perfekt.
Es ist also klar, dass es am Inhalt (Wert/Art/Typ) der Variable liegt, die offensichtlich immer und überall "Ping:3" zeigt, aber u.U. der ASCII-Code etc. unterschiedlich ist.
...ich bin noch am Testen, was UriEncode mir sagt... puh

Hallo Leute.
So langsam komm ich mir echt dämlich vor.
Seit Jahren schreibe ich die teils komplexesten Programm (z.B. eigene Fußbodenzeitungs-Steuerung, die damals noch gar nicht von Haus aus möglich war), und nun stehe ich vor einem scheinbar trivialen Problem, dass meine einfachsten Versuche nicht fruchten...

Also - ich mach über CUx virtuellem Gerät Ping-Abfragen zu diversen Geräten - funzt auch prima.
In einem Script möchte ich basierend auf Änderung (Ping kommt nicht zurück) lediglich abfragen, welches (virtuelle) Gerät das Script anwirft und demnach NUR einer Variable einen Namen verpassen.

Etwas reduziert und aufs wesentliche sieht das Script so aus:

Code: Alles auswählen

object o_src = dom.GetObject("$src$");
if(o_src)
{
 string o_geraet = dom.GetObject(o_src.Device()).Name();
}
else
{
 string o_geraet = "(Test, Programm manuell gestartet)";
}

integer valSuche;
string o_geraet_Name = "NoName";

! BIS HIER HER IST ALLES GUT

if(o_geraet.Find("1") >= 0)
{
 integer valSuche = o_geraet.Find("1");
 string o_geraet_Name = "WR1";
}
! ...weitere "IF's"
Fakt:
o_geraet ist immer korrekt.
(o_geraet kann z.B. Werte haben wie "Ping:1", "Ping:2" usw.)

Problem ist:
valSuche ist IMMER = o_geraet und NICHT die gefundene Position oder true/false.
Auch mit Contains erhalte ich in Variable valSuche kein True/False, sondern auch nur o_geraet - also den Namen, auch wenn ich der valSuche einen anderen Typ zuweise.
o_geraet_Name bleibt immer "NoName"
Zeitweise hatte ich es hinbekommen, dass überhaupt ein IF anspringt, dann war es aber das falsche, nämlich immer das letzte, vmtl. weil jede gültig war bis zum Durchlauf aller.

Lösungsansätze:
Ich hatte schon ALLES auf ToString(0) ...oder ohne Parameter versucht, kein Unterschied.
...ALLES bedeutet wirklich alles, z.B. auch im Find ( o_geraet.Finde("1").ToString(0) )
Wohl gemerkt, auch mit z.B...
if(o_geraet.ToString(0).Contains("1".ToString(0)) == true)
...egal ob mit oder ohne Parameter 0 funktioniert es nicht.

Wo mache ich denn hier einen fatalen Anfänger-Fehler?
Das ":" in z.B. "Ping:1" kann ja nicht das Problem sein, hier müsste ich nicht "escapen", uns selbst wenn, dann wäre manches Verhalten trotzdem nicht korrekt.
Die Doku gibt mir hier keine Aufschluss.
Zuletzt geändert von ACX_Com am 01.05.2024, 12:05, insgesamt 1-mal geändert.

Tyfys
Beiträge: 576
Registriert: 17.04.2021, 17:12
System: CCU
Hat sich bedankt: 29 Mal
Danksagung erhalten: 133 Mal

Re: Was zum Henker - if auf Contains, Find... funktioniert nicht

Beitrag von Tyfys » 01.05.2024, 11:40

ich hatte mich gestern grad mit Contains() rumgeärgert.

Scheint keine komplexen Ausdrücke zu mögen. Oder ich hatte (noch) zu wenig Klammern. Oder ?????

ich hab's dann auf diese Art gelöst:

Code: Alles auswählen

var b=  "213";
var a = ("1".ToString(0));
if( b.Contains(a) == true) {
WriteLine(b);
}
Allerdings sollte man nie Variablen in einem if-Block definieren

bei mir (CCU2) klappt es aber so:

Code: Alles auswählen

var o_geraet="213";
integer valSuche;
string o_geraet_Name;

if(o_geraet.Find("1") >= 0)
{
 valSuche = o_geraet.Find("1");
 o_geraet_Name = "WR1";
}
WriteLine(valSuche );
WriteLine(o_geraet_Name  );
Dann kann man die auch nach dem if-Block verwenden. Sonst kracht es da.
Gruß
Harry


ACX_Com
Beiträge: 12
Registriert: 09.07.2022, 09:52
System: CCU

Re: Was zum Henker - if auf Contains, Find... funktioniert nicht

Beitrag von ACX_Com » 01.05.2024, 12:40

Tyfys hat geschrieben:
01.05.2024, 11:40
ich hatte mich gestern grad mit Contains() rumgeärgert.

Scheint keine komplexen Ausdrücke zu mögen. Oder ich hatte (noch) zu wenig Klammern. Oder ?????

ich hab's dann auf diese Art gelöst:

Code: Alles auswählen

var b=  "213";
var a = ("1".ToString(0));
if( b.Contains(a) == true) {
WriteLine(b);
}
Allerdings sollte man nie Variablen in einem if-Block definieren

bei mir (CCU2) klappt es aber so:

Code: Alles auswählen

var o_geraet="213";
integer valSuche;
string o_geraet_Name;

if(o_geraet.Find("1") >= 0)
{
 valSuche = o_geraet.Find("1");
 o_geraet_Name = "WR1";
}
WriteLine(valSuche );
WriteLine(o_geraet_Name  );
Dann kann man die auch nach dem if-Block verwenden. Sonst kracht es da.
Das mit dem Setzen im IF (string...) habe ich geändert, das war aber nicht der Grund und nein, da hat nix gekracht. ;)
Bitte genau mein UPDATE beachten - wenn ich es mit manuell zugewiesener Variable statt dem Device-Name teste, habe ich keine Probleme und alles klappt.
Es MUSS also irgendeine Unstimmigkeit (Charcode) zwischen eingegebenen und gespeicherten / zu vergleichenden Werten geben, die ich noch nicht herausgefunden habe.
UriEncode überigens bringt mir nix, weil beim Script Testen immer das selbe "visuell" ankommt, nämlich "Ping:3"

ACX_Com
Beiträge: 12
Registriert: 09.07.2022, 09:52
System: CCU

Re: Was zum Henker - if auf Contains, Find... funktioniert nicht

Beitrag von ACX_Com » 01.05.2024, 12:41

Baxxy hat geschrieben:
01.05.2024, 11:59
Mich wundert das es nicht hier schon kracht...

Code: Alles auswählen

object o_src = dom.GetObject("$src$");
if(o_src)
{
 string o_geraet = dom.GetObject(o_src.Device()).Name();
}
Du meinst wegen "string.." im IF?
...ist schon geändert.
Ansonsten wäre eine näherer Hinweis, was du genau meinst hilfreich.

Tyfys
Beiträge: 576
Registriert: 17.04.2021, 17:12
System: CCU
Hat sich bedankt: 29 Mal
Danksagung erhalten: 133 Mal

Re: Was zum Henker - if auf Contains, Find... funktioniert nicht

Beitrag von Tyfys » 01.05.2024, 12:51

Baxxy hat geschrieben:
01.05.2024, 11:59
Mich wundert das es nicht hier schon kracht...
$src$ liefert doch eine ID. - Ist das bei CuxD anders ?

Wenn ich dann bei mir $src$ durch eine ID ersetze, liefert diese Konstruktion
überraschenderweise den Kanalnamen - aber nicht den erhofften Gerätenamen :

Code: Alles auswählen

object o_src = dom.GetObject("2779");
if(o_src)
{
 string o_geraet = dom.GetObject(o_src.Device()).Name();
}
else
{
 string o_geraet = "(Test, Programm manuell gestartet)";
}
WriteLine(o_geraet );
Gruß
Harry

Benutzeravatar
Baxxy
Beiträge: 10952
Registriert: 18.12.2018, 15:45
System: Alternative CCU (auf Basis OCCU)
Hat sich bedankt: 620 Mal
Danksagung erhalten: 2257 Mal

Re: Was zum Henker - if auf Contains, Find... funktioniert nicht

Beitrag von Baxxy » 01.05.2024, 12:53

Bekommst du keine Script Runtime Error im Log?

Du gibst ja nicht an was $src$ bei dir ist.
I.d.R. ist das ein Datenpunkt. (bzw. Datenpunkt-ID)

Welchen Namen möchtest du denn haben, den vom "Ping-Kanal" (mein Ping-Device hat 16 Kanäle) oder wirklich den vom Gerät?

Benutzeravatar
Baxxy
Beiträge: 10952
Registriert: 18.12.2018, 15:45
System: Alternative CCU (auf Basis OCCU)
Hat sich bedankt: 620 Mal
Danksagung erhalten: 2257 Mal

Re: Was zum Henker - if auf Contains, Find... funktioniert nicht

Beitrag von Baxxy » 01.05.2024, 12:56

Tyfys hat geschrieben:
01.05.2024, 12:51
$src$ liefert doch eine ID. - Ist das bei CuxD anders ?
Nein passt.
Tyfys hat geschrieben:
01.05.2024, 12:51
Wenn ich dann bei mir $src$ durch eine ID ersetze, liefert diese Konstruktion
überraschenderweise den Kanalnamen - aber nicht den erhofften Gerätenamen :
Jap.

Code: Alles auswählen

local0.warn ReGaHss: WARNING: incorrect use of Device() (use Channel()): object o_src = dom.GetObject(2145); if(o_src) {  string o_geraet = dom.GetObject(o_src.Device()).Name(); } [ExecDP():iseESPexec.cpp:8598]
local0.err ReGaHss: ERROR: ScriptRuntimeError: object o_src = dom.GetObject(2145); if(o_src) {  string o_geraet = dom.GetObject(o_src.Device()).Name(); } [ExecError():iseESPexec.cpp:12934]

ACX_Com
Beiträge: 12
Registriert: 09.07.2022, 09:52
System: CCU

Re: Was zum Henker - if auf Contains, Find... funktioniert nicht

Beitrag von ACX_Com » 01.05.2024, 13:02

Vielleicht habe ich nicht deutlich genug angegeben, was SRC ist - meinte es geht schon allein aus der Schreibweise "Ping:1" hervor.
Nochmal...
Es handelt sich um ein CUx (virtuelles) Device "Ping" und davon um Kanäle "Ping:1", "Ping:2", "Ping:3"... usw.

Und...

object o_src = dom.GetObject("$src$");
string o_geraet = dom.GetObject(o_src.Device()).Name();

...liefert mir immer (auch reproduzierbar nach Änderung des Kanal-Namens) den korrekten Namen.
Also z.B. auch, wenn ich diesen "PingA" nenne.

Wie schon gesagt, bis dahin habe ich keine Probleme.
Auch nicht mit Laufzeitfehlern.
Solange in einem IF und zwangsweise auch nach ELSE eine Variable definiert wird, sollte das doch eher die Regel sein, wieso sollte ich auch zuvor definieren, wenn SICHER eine der beiden IF-Bereiche anschlagen MUSS.!? :roll:

Ich schau mir Eure Tipps aber nochmal genauer an... ;) DANKE übrigens für Eure Unterstützung!

Benutzeravatar
Baxxy
Beiträge: 10952
Registriert: 18.12.2018, 15:45
System: Alternative CCU (auf Basis OCCU)
Hat sich bedankt: 620 Mal
Danksagung erhalten: 2257 Mal

Re: Was zum Henker - if auf Contains, Find... funktioniert nicht

Beitrag von Baxxy » 01.05.2024, 13:30

In einem Script innerhalb eines WebUI-Programmes ist $src$ niemals eine Kanal oder Geräte-ID.
In deinem Fall ist es wohl die ID des triggernden Datenpunktes, vermutlich STATE oder UNREACH_COUNTER des Ping-Device-Kanals.

Da du den Kanalnamen möchtest würde ich ihn so ermitteln:

Code: Alles auswählen

string o_geraet = (dom.GetObject(dom.GetObject(o_src).Channel())).Name();
Auch wenn deine Methode ohne Fehler funktioniert (vermutlich CCU2/3) ist das nicht "richtig".

Zum "probieren":

Code: Alles auswählen

object o_src = dom.GetObject("$src$");
string sChn_Name;
string sGeraet_Name = "NoName";
if(o_src) { sChn_Name = (dom.GetObject(dom.GetObject(o_src).Channel())).Name(); }
 else { sChn_Name = "(Test, Programm manuell gestartet)"; }

if (sChn_Name.Contains(":1")){ sGeraet_Name = "WR1";}
 elseif (sChn_Name.Contains(":2")) { sGeraet_Name = "WR2";}
  elseif (sChn_Name.Contains(":3")) { sGeraet_Name = "WR3";}

WriteLine(sGeraet_Name);
Eigentlich braucht man das aber alles gar nicht.
$src$ ist der Programmtrigger, es würde also reichen einfach den Namen des Trigger-Kanals direkt zu nutzen.

Antworten

Zurück zu „Softwareentwicklung für die HomeMatic CCU“