Translate from javascript to rules DSL

You could recreate your Items to follow a set naming pattern.

If you know it will always be “_Lamp”, for example you can use replace.

i.name.replace("_Lamp", "_ColorTemperature")

They are all parts of the Java Classes you are working with.

Method Where it’s maintained Link to JavaDocs
.name openHAB, part of Item GenericItem (openHAB Core 4.2.0-SNAPSHOT API)
.split Core Java, part of String String (Java SE 11 & JDK 11 )
.get(0) Core Java, Rules DSL converts arrays to an ArrayList. ArrayList (Java SE 11 & JDK 11 )
.head Part of Xtend’s way to process Lists. Their docs are all over the place though. It’s a layer on top of Java’s Stream API. I’ve consolidated this at the following DP. Design Pattern: Working with Groups in Rules

Doh, I’ve been away from Rules DSL for too long.

Like I said, save each step to it’s own variable instead of trying to do everything all on one line.

val members = gAll_Lights_Brightness.members
logInfo("test", "All members: " + members)
val filtered = members.filter[i | i.state as Number > 0]
logInfo("test", "Filtered: " + filtered)
filtered.forEach[item |
    logInfo("test", "Processing Item " + item.name)
    // here is where it's better to do String manipulation to convert item.name to the ColorTemperature
    // Item's name, even if it means you have to rename those Items to fit the pattern
    // sendCommand(item.name.replace("Lamp", "ColorTemperature"), newState.toString)
    // or maybe it's as simple as
    // sendCommand(item.name + "_ColorTemperature", newState.toString)

    // As explained in the working with groups DP linked above, use findFirst instead of filter and head
    val commandItem = gAll_Lights_ColorTemperature.members.findFirst[ j | j.name.contains(item.name) ]
    logInfo("test", "Color Item found is " + commandItem) // if this is null the Item was not found
    commandItem.sendCommand(newState)
]

Break it up and log each step of the way. If you do half a dozen operations all on the same line and it doesn’t work it’s impossible to figure out why.

1 Like

These are features of the Xtend language upon which DSL is based.
In turn that’s based on Java, so Java tutorials will give you insight into what you can do to with a Java string object.

If you choose a more consistent Item naming convention, you make it easier for yourself.
(I expect most of us oldtimers have gone through several renaming/restructuring exercises already).

However;

val randomName = "some_old_rubbish_lamp"
val parts = randomName.split("_") 
var n = 0
var newName = ""
while (parts.get(n) != "lamp") {
    newName = newName + parts.get(n) + "_"
    // remember to put the underscores back
    n = n + 1
}
newName = newName + "brightness"
logInfo("test", "new name " + newName)
// logs out string "some_old_rubbish_brightness"

More than one way to do this I expect.

lastIndexOf('_') being the cunning part here

Thank you all.

I’ve learnt maybe 1% of what you’ve laid out here so far, but I’ll keep going.

My rule now works and I can go about cleaning it up, refining it, and tweaking it further.

Here are the finished rules:

rule "Sun Color Temperature - Set Color Temperature by Sun Elevation"
when
    Item AstroSunData_Elevation changed 
then
    logInfo("Color Temperature", "Sun elevation has changed, updating Calculated Color Temperture if necessary")
    if (newState >= -6) {
        val SunElevation = (AstroSunData_Elevation.state as Number + 6).intValue
        val Number Clouds = Localweatherandforecast_Cloudiness.state
        val weatherCond = Localweatherandforecast_WeatherCondition.state
        val weatherID = Localweatherandforecast_Current_Conditionid.state
        val outputstart = 2200
        val outputend = 6000
        val inputstart = 0
        val inputend = 46
        val Number output1 = outputstart + (outputend - outputstart) / (inputend - inputstart) * (SunElevation - inputstart)
        val Number output2 = Math.min(Math.max(output1, 2200), 6000) 

        val Number cloudFactor = Math.floor( (output2.intValue - 2200) * (Clouds.intValue * 0.002))
        val Number newColourValue = Math.min(Math.max((output2.intValue - cloudFactor.intValue), 2200), 6000)

   
            Calculated_ColorTemperature.sendCommand(newColourValue)
            logInfo("Color Temperature", "Calculated Temp is " + output2 + "K - Cloud Factor (" + Clouds + ". Calculated as " + cloudFactor + "K) = " + (output2 - cloudFactor) + "K")
        
    }
end

rule "Sun Color Temperature - Send Calculated Color to all lights thata are ON"
when
    Item Calculated_ColorTemperature received update 
then
    logInfo("Color Temperature", "Applying Color Temperature to all lights that are ON")
    gAll_Lights_Brightness.members.filter[i|(i.state as Number) > 0].forEach[item|
        gAll_Lights_ColorTemperature.members.filter[j|j.name.contains(item.name.replace("_Brightness", "_ColorTemperature"))].head.sendCommand(newState)
        
    ]
end
end```