Skip to content

QuantityType Percent cast to HSBType, OnOffType and OpenClosedType is broken #5084

@Joachim2709

Description

@Joachim2709

QuantityType Percent cast (as) to HSBType, UpDownType, OnOffType and OpenClosedType is broken. Caused by a wrong internal representation?

Only '1%' maps to the UpDownType.DOWN, OnOffType.ON or OpenClosedType.OPEN. For a cast to HSBType an exception is thrown for '100%' and '1%' results in a brightness value of 100!!

Expected behavior is that for UpDownType '100%' maps to DOWN only and for OnOffType or OpenClosedType any value greater ZERO maps to OnOffType.ON or OpenClosedType.OPEN.
For HSBType the value range should be 0-100% instead 0-1%.

Following groovy script can be used to reproduce the problem:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Logger log = LoggerFactory.getLogger('QuantityType Test');

log.warn('QuantityType(100 %).as(UpDownType.class) = {}', new QuantityType('100 %').as(UpDownType.class));
log.warn('QuantityType(1 %).as(UpDownType.class) = {}', new QuantityType('1 %').as(UpDownType.class));
log.warn('QuantityType(100 %).as(OnOffType.class) = {}', new QuantityType('100 %').as(OnOffType.class));
log.warn('QuantityType(1 %).as(OnOffType.class) = {}', new QuantityType('1 %').as(OnOffType.class));
log.warn('QuantityType(100 %).as(OpenClosedType.class) = {}', new QuantityType('100 %').as(OpenClosedType.class));
log.warn('QuantityType(1 %).as(OpenClosedType.class) = {}', new QuantityType('1 %').as(OpenClosedType.class));
log.warn('QuantityType(1 %).as(HSBType.class) = {}', new QuantityType('1 %').as(HSBType.class));
try {
    log.warn('QuantityType(100 %).as(HSBType.class) = {}', new QuantityType('100 %').as(HSBType.class));
} catch(exp) {
    log.error('QuantityType(100 %).as(HSBType.class) =', exp);
}

The script produces the following output:

2025-10-18 10:51:11.134 [WARN ] [QuantityType Test                   ] - QuantityType(100 %).as(UpDownType.class) = null
2025-10-18 10:51:11.136 [WARN ] [QuantityType Test                   ] - QuantityType(1 %).as(UpDownType.class) = DOWN
2025-10-18 10:51:11.137 [WARN ] [QuantityType Test                   ] - QuantityType(100 %).as(OnOffType.class) = ON
2025-10-18 10:51:11.138 [WARN ] [QuantityType Test                   ] - QuantityType(1 %).as(OnOffType.class) = ON
2025-10-18 10:51:11.139 [WARN ] [QuantityType Test                   ] - QuantityType(100 %).as(OpenClosedType.class) = null
2025-10-18 10:51:11.140 [WARN ] [QuantityType Test                   ] - QuantityType(1 %).as(OpenClosedType.class) = OPEN
2025-10-18 10:51:11.142 [WARN ] [QuantityType Test                   ] - QuantityType(1 %).as(HSBType.class) = 0,0,100
2025-10-18 10:51:11.143 [ERROR] [QuantityType Test                   ] - QuantityType(100 %).as(HSBType.class) =
java.lang.IllegalArgumentException: Value must be between 0 and 100
	at org.openhab.core.library.types.PercentType.validateValue(PercentType.java:95) ~[?:?]
	at org.openhab.core.library.types.PercentType.<init>(PercentType.java:90) ~[?:?]
	at org.openhab.core.library.types.QuantityType.as(QuantityType.java:578) ~[?:?]
	at org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:321) ~[?:?]
	at test.run(test.groovy:15) ~[?:?]
	at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:331) ~[?:?]
	at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:161) ~[?:?]
	at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:137) ~[?:?]
	at javax.script.AbstractScriptEngine.eval(Unknown Source) ~[java.scripting:?]
	at org.openhab.core.automation.module.script.internal.ScriptEngineManagerImpl.loadScript(ScriptEngineManagerImpl.java:165) ~[?:?]
	at org.openhab.core.automation.module.script.rulesupport.loader.AbstractScriptFileWatcher.createAndLoad(AbstractScriptFileWatcher.java:335) ~[?:?]
	at org.openhab.core.automation.module.script.rulesupport.loader.AbstractScriptFileWatcher.lambda$13(AbstractScriptFileWatcher.java:309) ~[?:?]
	at java.util.concurrent.CompletableFuture$AsyncRun.run(Unknown Source) ~[?:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[?:?]
	at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[?:?]
	at java.lang.Thread.run(Unknown Source) [?:?]

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugAn unexpected problem or unintended behavior of the Core

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions