FunctionSensor extends AbstractAddSensorFeed<T> { @Override public void apply(final EntityLocal entity) { AttributeSensor<T> sensor = addSensor(entity); if (LOG.isDebugEnabled()) { LOG.debug("Adding HTTP JSON sensor {} to {}", initParam(SENSOR_NAME), entity); } final ConfigBag allConfig = ConfigBag.newInstanceCopying(initParams()); final Callable<?> function = EntityInitializers.resolve(allConfig, FUNCTION); final Boolean suppressDuplicates = EntityInitializers.resolve(allConfig, SUPPRESS_DUPLICATES); final Duration logWarningGraceTimeOnStartup = EntityInitializers.resolve(allConfig, LOG_WARNING_GRACE_TIME_ON_STARTUP); final Duration logWarningGraceTime = EntityInitializers.resolve(allConfig, LOG_WARNING_GRACE_TIME); FunctionPollConfig<?, T> pollConfig = new FunctionPollConfig<Object, T>(sensor) .callable(function) .onFailureOrException(Functions.constant((T) null)) .suppressDuplicates(Boolean.TRUE.equals(suppressDuplicates)) .logWarningGraceTimeOnStartup(logWarningGraceTimeOnStartup) .logWarningGraceTime(logWarningGraceTime) .period(initParam(SENSOR_PERIOD)); FunctionFeed feed = FunctionFeed.builder().entity(entity) .poll(pollConfig) .build(); entity.addFeed(feed); } FunctionSensor(final ConfigBag params); protected  FunctionSensor(); @Override void apply(final EntityLocal entity); @SuppressWarnings("serial")
    static final ConfigKey<Callable<?>> FUNCTION; }
@Test public void testFunction() throws Exception { AtomicReference<String> val = new AtomicReference<String>("first"); Callable<String> callable = new Callable<String>() { @Override public String call() throws Exception { return val.get(); } }; FunctionSensor<Integer> initializer = new FunctionSensor<Integer>(ConfigBag.newInstance() .configure(FunctionSensor.SENSOR_PERIOD, Duration.millis(10)) .configure(FunctionSensor.SENSOR_NAME, SENSOR_STRING.getName()) .configure(FunctionSensor.SENSOR_TYPE, STRING_TARGET_TYPE) .configure(FunctionSensor.FUNCTION, callable)); initializer.apply(entity); entity.sensors().set(Attributes.SERVICE_UP, true); initializer.apply(entity); entity.sensors().set(Attributes.SERVICE_UP, true); EntityAsserts.assertAttributeEqualsEventually(entity, SENSOR_STRING, "first"); val.set("second"); EntityAsserts.assertAttributeEqualsEventually(entity, SENSOR_STRING, "second"); }