Seite 1 von 1

There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a

Verfasst: 1. Feb 2026 17:25
von TomW80
Leider hat mich der Beitrag viewtopic.php?t=9529 nicht weitergebracht bei meinen rules.
Kann mir jemand einen Tip geben?

Die eine rule sieht so aus:

Code: Alles auswählen

rule "geöffnete Fenster zählen"
when 
    Member of gKontakte changed or
    Item KG_Kellerfenster changed
then

    if (kontakteoffen.state == NULL) 
    {
        kontakteoffen.postUpdate(0)
    }

    var Integer nAnz = gKontakte.members.filter[i|i instanceof ContactItem ].filter[s|s.state==OPEN].size
    nAnz = nAnz + gKontakte.members.filter[i|i instanceof SwitchItem ].filter[ s|s.state==ON].size
    kontakteoffen.postUpdate( nAnz )
end
Wenn ich das folgende

Code: Alles auswählen

.filter[s|s.state==OPEN].size
so schreibe,

Code: Alles auswählen

.filter[ContactItem s|s.state==OPEN].size
erhalte ich den Fehler
Type mismatch: cannot convert from (ContactItem)=>boolean to Function1<? super Item, Boolean>
Wie übergebe ich den richtigen Typ

Re: There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures in

Verfasst: 1. Feb 2026 17:45
von TomW80
Jetzt kommt auf einmal kein Fehler mehr wenn ich es so schreibe.

Code: Alles auswählen

var Integer nAnz = gKontakte.members.filter[i|i instanceof ContactItem ].filter[ NumberItem s|s.state==OPEN].size
nAnz = nAnz + gKontakte.members.filter[i|i instanceof SwitchItem ].filter[ NumberItem s|s.state==ON].size
Muss nur noch schauen ob der Fehler weg ist.

Re: There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures in

Verfasst: 2. Feb 2026 19:47
von TomW80
TomW80 hat geschrieben: 1. Feb 2026 17:45 Jetzt kommt auf einmal kein Fehler mehr wenn ich es so schreibe.

Code: Alles auswählen

var Integer nAnz = gKontakte.members.filter[i|i instanceof ContactItem ].filter[ NumberItem s|s.state==OPEN].size
nAnz = nAnz + gKontakte.members.filter[i|i instanceof SwitchItem ].filter[ NumberItem s|s.state==ON].size
Muss nur noch schauen ob der Fehler weg ist.
Zu früh gefreut, VSC meckert heute wieder mit dem o.g. Fehler.
Jemand nun eine Idee wie die rule aussehen muss?

Re: There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures in

Verfasst: 3. Feb 2026 03:05
von udo1toni
Zunächst mal sieht der Code korrekt aus.
Insbesondere funktioniert die Rule bei mir einwandfrei und auch VS Code ist glücklich.
Welche (exakte) Version von openHAB nutzt Du denn?
Sind in der Datei noch andere Rules vorhanden?

Ein anderer Punkt ist allerdings, dass Du Dir an dieser Stelle zu viel Arbeit machst. :)

Code: Alles auswählen

rule "geöffnete Fenster zählen"
when 
    Member of gKontakte changed
then
    var Integer iAnz = gKontakte.members.filter[s|s.state==OPEN || s.state==ON].size
    kontakteoffen.postUpdate(iAnz)
end
reicht.
Punkt 1: KG_Kellerfenster ist ja wohl Member der Group gKontakte (sonst wird es nicht mitgezählt...)
Punkt 2: Ich gehe davon aus, dass sich in der Gruppe gKontakte nur Kontakte und Switches befinden. Ein Switch Item kann die Status ON, OFF und NULL annehmen. Ein Contact Item kann die Zustände OPEN, CLOSED und NULL annehmen. Wenn Du prüfst, ob ein Switch Item OPEN ist, wird das Ergebnis false sein, ebenso wenn Du bei einem Contact Item auf ON prüfst. Es gibt aber keinen Fehler und auch kein Fehlverhalten.
Der Filter ist ein Bool'scher Ausdruck, da Dich die Summe interessiert, passt das mit dem logischen Oder.
Ob Du hier die Variable als nAnz oder iAnz festlegst, ist egal :) ich habe nur die Macke, den ersten Buchstaben abhängig vom Datentyp (hier Integer) zu verwenden.
Punkt 3: JE nach verwendetem Binding könnte es auch sinnvoll sein, das Eingangssignal des Kellerfenstersensors ebenfalls als Contact abzubilden, das sollte eigentlich immer gehen (bei einigen Addons vielleicht mit einem Umweg verbunden, dennoch...)
Punkt 4: Du kannst auch komplett auf die Rule verzichten und stattdessen gKontakte als Group:Number:COUNT(".*N") definieren, dann zählt das Group Item alle Member, deren Status auf "N" endet.

Ach so... Die Überschrift ist unglücklich. Wir sind hier ein deutschsprachiges Forum und es kommen immer wieder Bots durch, die mit englischen Überschriften auffallen, da ist die Chance groß, eine solche Überschrift reflexhaft als Spam wahrzunehmen.
Besser wäre also notfalls eine Überschrift wie: "Brauche Hilfe bei einer Rule" und dann innerhalb des Postings die Fehlermeldung (als Code markiert...)

Re: There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures in

Verfasst: 3. Feb 2026 10:13
von TomW80
Hallo udo1toni,

Danke für deine ausführliche Erklärung, werde Punkt 4 nutzen um die Rule zu sparen. :)
Ich verwende OH 5.1.1

Re: There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures in

Verfasst: 4. Feb 2026 13:45
von TomW80
Ich habe in einer zweite Rule genau das gleiche Problem.
Wenn ich das NumberItem (rot) einfüge, erhalte ich den Fehler wie oben schon angegeben.
Type mismatch: cannot convert from (NumberItem)=>boolean to Function1<? super Item, Boolean>
Nach dem .forEach funktioniert das mit dem NumberItem.

Jemand eine Idee wie ich es hier schreiben muss?

Code: Alles auswählen

...
 Temperaturen_all.members.filter[ NumberItem i|i.state<=(fensterOffenWarnungTemperatur.state as Number)].forEach[NumberItem j|    
		 	var String tempitem =  j.name 
            val Number tempvalue = (j.state as Number)
			
            if (now.getHour() >= 22 || now.getHour() <= 7) // keine Nachricht zwischen 22 Uhr und 07 Uhr versenden
            {
                logInfo("Raumtemperatur","Nachricht nicht gesendet, da es Nacht ist")
            }
            else if (gKontakte.state > 0)
            {
                // Meldetext erzeugen
                meldeText = 'Die Temperatur im Raum ' + tempitem.replaceAll('KG_','Kellergeschoß_').replaceAll('EG_','Erdgeschoß ').replaceAll('OG_','Obergeschoß ').replaceAll('_Temp',' ').replaceAll('Kind2_XTemp','Theo ').replaceAll('SpeisXTemp','Speis ') + 'ist kleiner als ' + (fensterOffenWarnungTemperatur.state as Number) + '°C! Aktuell: ' + tempvalue + '°C'

                //Pushover
                val actions = getActions("pushover", "pushover:pushover-account:***")
                actions.sendMessage("Information", meldeText)
                
            }   
            else
            {
                logInfo("Raumtemperatur","Nachricht nicht gesendet, da kein Fenster mehr offen ist")
            } 
		]
...

Re: There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures in

Verfasst: 5. Feb 2026 18:13
von udo1toni
Warum fügst Du da überhaupt NumberItem ein? Das ist unnötig.

Der Codeschnipsel sieht außerdem nicht gut aus ;) Warum fragst Du die Uhrzeit innerhalb der Iteration über alle Items ab? Warum prüfst Du innerhalb der Iteration, ob alle Fenster geschlossen sind? Besser:

Code: Alles auswählen

...
if(now.getHour() >= 22 || now.getHour() < 7)                               // keine Nachricht zwischen 22 Uhr und 07 Uhr versenden
    logInfo("Raumtemperatur","Nachricht nicht gesendet, da es Nacht ist")
else if((gKontakte.state as Number) == 0)
    logInfo("Raumtemperatur","Nachricht nicht gesendet, da kein Fenster mehr offen ist")
else {
    val Number minTemp = fensterOffenWarnungTemperatur.state as Number
    Temperaturen_all.members.filter[i|(i.state as Number) <= minTemp].forEach[j|
        var String tempitem =  j.name 
        val Number tempvalue = j.state as Number
        meldeText = 'Die Temperatur im Raum ' + tempitem.replaceAll('KG_','Kellergeschoß_').replaceAll('EG_','Erdgeschoß ').replaceAll('OG_','Obergeschoß ').replaceAll('_Temp',' ').replaceAll('Kind2_XTemp','Theo ').replaceAll('SpeisXTemp','Speis ') + 'ist kleiner als ' + minTemp.toString + ' °C! Aktuell: ' + tempvalue.toString + ' °C'
        val actions = getActions("pushover", "pushover:pushover-account:***")         //Pushover
        actions.sendMessage("Information", meldeText)
    ]
}
...
Der Ruleschnipsel erzeugt für jede Unterschreitung eine eigene Pushover Meldung, falls mehrere Temperaturen unterschritten sind. Es wäre eventuell besser, zunächst alle Items abzufragen und eine einzige Meldung zu generieren.
Auch das Konstrukt mit dem replaceAll wirkt eher wie eine Notbehelf :) möglicherweise ist das Label eindeutig? Ansonsten bliebe noch eine HashMap, um das etwas übersichtlicher zu bekommen.

Code: Alles auswählen

// global definieren
val HashMap<String, String> hmNames = newHashMap(
    "KG_Raum1" -> "Kellergeschoss Raum 1",
    "KG_Raum2" -> "Kellergeschoss Raum 2",
    "KG_Raum3" -> "Kellergeschoss Raum 3"
)
...
rule ...
    val String strText    = hmNames.get(j.name)
    val String strTemp    = String.format("%.1f °C",(j.state as Number))
    val String strTempMin = String.format("%.1f °C",minTemp)
    meldeText = 'Die Temperatur im Raum ' + strText + ' ist kleiner als ' + strTempMin + ' Aktuell: ' + strTemp
    val actions = getActions("pushover", "pushover:pushover-account:***")                                       //Pushover
    actions.sendMessage("Information", meldeText)
...
Eine HashMap liefert für jeden Eingangswert einen Ausgangswert. Natürlich sollte der Eingangswert auch in der Liste enthalten sein :)

Re: There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures in

Verfasst: 7. Feb 2026 13:15
von TomW80
udo1toni hat geschrieben: 5. Feb 2026 18:13 Warum fügst Du da überhaupt NumberItem ein? Das ist unnötig.
Na wegen dem Fehler: "There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context."

Eigentlich hat die Rule immer funktioniert, nur taucht der Fehler oben beim start von openhab seit neustem immer auf und läd dadurch die Rule nicht.
Ich habe die Rule jetzt mal so geändert, Fehler taucht aber immer noch auf.

Code: Alles auswählen

rule "Benachrichtigung Temperatur"
when
    Member of Temperaturen_all changed
then

    // Check ob Variablen passen, ansonsten defaultwert setzen
    if ((NotificationTemperatur.state != OFF) && (NotificationTemperatur.state != ON)) {
        NotificationTemperatur.sendCommand(ON)
        logInfo('rules', logPrefix + 'Setze Default-Wert für NotificationTemperatur=An')
    }
    if (fensterOffenWarnungTemperatur.state == NULL) {
        fensterOffenWarnungTemperatur.postUpdate(17)
        logInfo('rules', logPrefix + 'Setze Default-Wert für fensterOffenWarnungTemperatur=17')
    }
    val Number minTemp = fensterOffenWarnungTemperatur.state as Number

    if (NotificationTemperatur.state == ON)
    {
      if(((Temperaturen_all.members.filter[i|(i.state as Number) <= minTemp]).size > 0) && (nNotifications == 0))
      {    
        nNotifications = 1

        if(now.getHour() >= 22 || now.getHour() < 7)                               // keine Nachricht zwischen 22 Uhr und 07 Uhr versenden
            logInfo("Raumtemperatur","Nachricht nicht gesendet, da es Nacht ist")
        else if((gKontakte.state as Number) == 0)
            logInfo("Raumtemperatur","Nachricht nicht gesendet, da kein Fenster mehr offen ist")
        else {           
            Temperaturen_all.members.filter[i|(i.state as Number) <= minTemp].forEach[j|
            var String tempitem =  j.name 
            val Number tempvalue = j.state as Number
            meldeText = 'Die Temperatur im Raum ' + tempitem.replaceAll('KG_','Kellergeschoß_').replaceAll('EG_','Erdgeschoß ').replaceAll('OG_','Obergeschoß ').replaceAll('_Temp',' ').replaceAll('Kind2_XTemp','Theo ').replaceAll('SpeisXTemp','Speis ') + 'ist kleiner als ' + minTemp.toString + ' °C! Aktuell: ' + tempvalue.toString + ' °C'
            val actions = getActions("pushover", "pushover:pushover-account:***")         //Pushover
            actions.sendMessage("Information", meldeText)
    ]
        }

        tFenstertemp = createTimer(now.plusMinutes(15))[  // Timer damit die Meldung nur alle 15 Minuten kommt und nicht ständig
        nNotifications = 0
        ]   
      }
    }

end

Re: There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures in

Verfasst: 7. Feb 2026 18:12
von udo1toni
Bist Du sicher, dass die Rule tatsächlich nicht geladen wird? Taucht sie in der Main UI nicht auf?
Das Verhalten erscheint mir seltsam, ich kann das bei mir auch nicht nachvollziehen, ich habe massig Rules mit members.filter[], das müsste dann ja bei mir auch auftreten.

Re: There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures in

Verfasst: 7. Feb 2026 19:17
von TomW80
Ja, da bin ich mir sicher.
Screenshot 2026-02-07 190957.jpg
openhab versucht die Rule zu laden, erkennt einen Fehler und entlädt sie dann wieder.

Wenn ich nach erfolgreichem Start von openhab die Datei mit der Rule neu abspeichere, wird die Rule geladen.
In diesem Beitrag habe ich das dazu gelesen.
at compile time (i.e. when the Rules are loaded) the Rules Engine can’t figure out what type is being used in the lambdas (everything between is a lambda). In particular, it can’t figure out what the type of ITEM is in the first filter in your first Rule or i isin the Windows filter in your second rule.
Und das ist wohl auch mein Problem.