Multiple Bean Instances
By default, SmartBeans creates a single instance of each bean. However, it also supports creating multiple instances of the same bean class when needed. Consider a scenario where you have a bean that controls a light with a motion sensor. If you need to control multiple lights with different motion sensors, it's more efficient to implement a single bean class and create separate instances for each light-sensor combination.
The @SmartBeanDef
annotation facilitates this multi-instance capability. This annotation can be applied multiple times
to the same bean class. Each annotation instance requires a unique name
attribute that distinguishes it from other
instances of the same bean class. This name must be unique across all instances of that specific bean class.
@SmartBeanDef(name = "KitchenMotion")
@SmartBeanDef(name = "BathroomMotion")
public class MotionControl implements SmartBean {
}
This example creates two distinct instances of the MotionControl
bean class, one named "KitchenMotion" and one named
"BathroomMotion". Creating multiple instances of the same bean without differentiation would have limited utility.
However, in this scenario, each instance is intended to serve a specific purpose: controlling different lights based on
input from different motion sensors. The "KitchenMotion" instance should respond to the kitchen motion sensor to control
the kitchen lighting, while the "BathroomMotion" instance should respond to the bathroom motion sensor to control the
bathroom lighting.
Bean Parameters
Bean parameters can be used to configure each instance of a bean class. For example, if you want to configure the
"KitchenMotion" instance to use a different motion sensor, you can do so by creating a sensor
parameter and set it to the
appropriate value. The same applies to the light you want to control. So our bean will have two parameters: sensor
and
light
. To set these parameters, you can use the params
attribute of the @SmartBeanDef
annotation.
@SmartBeanDef(name = "KitchenMotion", params = {
@Param(name = "light", value = "light.kitchen_ceiling"),
@Param(name = "sensor", value = "binary_sensor.kitchen_motion")
})
@SmartBeanDef(name = "BathroomMotion", params = {
@Param(name = "light", value = "light.mirror_cabinet"),
@Param(name = "sensor", value = "binary_sensor.bathroom_motion")
})
public class MotionControl implements SmartBean {
}
The name of a parameter must contain only alphanumeric characters, hyphens and underscores.
Accessing Bean Parameters
The simplest approach to access configuration parameters is to reference them directly within annotations in your bean
class. This can be done, for instance, through an @Entity
annotation on an instance field or a trigger annotation on
a bean method. To retrieve the value of a parameter named paramName
, use the expression syntax ${paramName}
within
the annotation's attributes. This expression will be evaluated and replaced with the actual parameter value at runtime.
@SmartBeanDef(name = "KitchenMotion", params = {
@Param(name = "light", value = "light.kitchen_ceiling"),
@Param(name = "sensor", value = "binary_sensor.kitchen_motion")
})
@SmartBeanDef(name = "BathroomMotion", params = {
@Param(name = "light", value = "light.mirror_cabinet"),
@Param(name = "sensor", value = "binary_sensor.bathroom_motion")
})
public class MotionControl implements SmartBean {
@Entity("${light}")
private Light light;
@OnStateTrigger(entity = "${sensor}", to = "on")
public void onMotion() {
light.turnOn();
}
}
You can also use parameters to construct a string as demonstrated in the following example.
@SmartBeanDef(name = "KitchenMotion", params = {
@Param(name = "room", value = "kitchen")
})
@SmartBeanDef(name = "BathroomMotion", params = {
@Param(name = "room", value = "bathroom")
})
public class MotionControl implements SmartBean {
@Entity("light.${room}_ceiling")
private Light light;
@OnStateTrigger(entity = "binary_sensor.${room}_motion", to = "on")
public void onMotion() {
light.turnOn();
}
}
Another approach to parameter access is through the SmartBeans
API's getParameter(String)
method. This method
returns a BeanParameter
object that provides several utility methods for efficiently retrieving the parameter's value
with proper type handling.
@SmartBeanDef(name = "KitchenMotion", params = {
@Param(name = "room", value = "kitchen")
})
@SmartBeanDef(name = "BathroomMotion", params = {
@Param(name = "room", value = "bathroom")
})
public class MotionControl implements SmartBean {
private SmartBeans sb;
@OnStateTrigger(entity = "binary_sensor.${room}_motion", to = "on")
public void onMotion() {
sb.log("Motion detected in the %s.", sb.getParameter("room").asString());
}
}
Using Default Values
Parameters can be made optional by specifying a default value that will be used when the parameter is not provided. This
is achieved using the syntax ${paramName|defaultValue}
, where the value after the pipe symbol serves as the fallback
value if the parameter is undefined or empty. The example below demonstrates this functionality.
@SmartBeanDef(name = "KitchenMotion", params = {
@Param(name = "lightOffTimeout", value = "00:00:30")
})
@SmartBeanDef(name = "BathroomMotion")
public class MotionControl implements SmartBean {
@TimerDef(interval = @Interval("${lightOffTimeout|00:01:00}"))
private Timer lightOffTimer;
}
The motion controller for the kitchen has a light-off timeout configured as 30 seconds (00:00:30
). If no value is
explicitly provided for the lightOffTimeout
parameter, as in the instance for the bathroom, the system will apply the
default value of 1 minute (00:01:00
).