Looking for optimal datastructure

I would use Items and a Group or Design Pattern: Associated Items to link the three together. Then the rule would be something like:

PlantsMoisture.members.forEach[moisture |
    val curr = moisture.state as Number
    val min = PlantsMoistureRanges.findFirst[min | min.name == moisture.name+"_Min"].state as Number
    val max = PlantsMoistureRanges.findFirst[max | max.name == moisture.name+"_Max"].state as Number

    if(curr > max){
        // Alert that plant is too wet, use DP: Human Readable Names to use a nice name in the alert
    }
    else if(curr < min){
        // Alert that the plant is to dry
    }
]

You don’t say what you want to do with fertilization, but I suspect the same could be used.

With this approach, you can use a setpoint or slider in your sitemap to set your min and max values instead of having them hardcoded in rules. You would probably want to set up persistence on those Items too so your custom values survive a reboot. You also might need a System started rule to populate the min and max values the very first time after creating the Item