openhab/openhab-core

QuantityType<Dimensionless> with unit one wrong update to item with different unit set

Closed this issue · 2 comments

An Number<Dimensionless> item with a unit set in metadata to something different from the default of one will not update correctly in a postUpdate with a QuantityType<Dimensionless> and unit one.

This is because the unit (one) gets dropped here . As there is no unit, postUpdate will assume it is a Number item and update with the configured unit.

To test this I created an Item Test with unit % and pattern %,.2f %%.

I tested with the javascript below (result is similar with DSL). Notice I tried updating the result of the division 4 times, once straight, twice after conversion to a compatible unit (I even used dB), and once where I explicitly appended one to the result. The timeouts are there to wait for the update to happen before logging.
The postUpdate in test 1 is the one producing the wrong result.

Issue was first discussed on the community: https://community.openhab.org/t/inconsistent-percentage-behaviour/154595/20?u=mherwege

var logger = log('Test');

var bkw    = Quantity('5 W')
var zwl    = Quantity('5 W')
var result = bkw.divide(bkw.add(zwl))   // I want to preserve the QuantityType for logging

logger.info('Result of calculation is: {}', result.toString())
logger.info('Unit is: {}', result.unit) // I would actually expect this to show `ONE`
logger.info('Dimension is: {}', result.dimension)
logger.info('Result %: {}', result.toUnit('%').toString())

logger.info('Test 1, no unit applied: {}', result.toString())
items.Test.postUpdate(result)
setTimeout(() => {
  logger.info('State: {}', items.Test.state)  
  logger.info('Test 2, % unit applied: {}', result.toUnit('%').toString())
  items.Test.postUpdate(result.toUnit('%'))
  setTimeout(() => {
    logger.info('State: {}', items.Test.state)
    logger.info('Test 3, dB unit applied: {}', result.toUnit('dB').toString())
    items.Test.postUpdate(result.toUnit('dB'))
    setTimeout(() => {
      logger.info('State: {}', items.Test.state)
      logger.info('Test 4, one appended: {}', result.toString() + ' one')
      items.Test.postUpdate(result.toString() + ' one')
      setTimeout(() => {
        logger.info('State: {}', items.Test.state)  
      }, 1000)
    }, 1000)
  }, 1000)
}, 1000)

Here is the log output with the problem in test 1:

==> /var/log/openhab/openhab.log <==
2024-04-02 18:17:51.042 [INFO ] [g.openhab.automation.openhab-js.test] - Result of calculation is: 0.5
2024-04-02 18:17:51.044 [INFO ] [g.openhab.automation.openhab-js.test] - Unit is: One
2024-04-02 18:17:51.046 [INFO ] [g.openhab.automation.openhab-js.test] - Dimension is: one
2024-04-02 18:17:51.049 [INFO ] [g.openhab.automation.openhab-js.test] - Result %: 50 %
2024-04-02 18:17:51.051 [INFO ] [g.openhab.automation.openhab-js.test] - Test 1, no unit applied: 0.5
==> /var/log/openhab/events.log <==
2024-04-02 18:17:51.056 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Test' changed from 50 % to 0.5 %
==> /var/log/openhab/openhab.log <==
2024-04-02 18:17:52.056 [INFO ] [g.openhab.automation.openhab-js.test] - State: 0.5 %
2024-04-02 18:17:52.060 [INFO ] [g.openhab.automation.openhab-js.test] - Test 2, % unit applied: 50 %
==> /var/log/openhab/events.log <==
2024-04-02 18:17:52.069 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Test' changed from 0.5 % to 50 %
==> /var/log/openhab/openhab.log <==
2024-04-02 18:17:53.070 [INFO ] [g.openhab.automation.openhab-js.test] - State: 50 %
2024-04-02 18:17:53.074 [INFO ] [g.openhab.automation.openhab-js.test] - Test 3, dB unit applied: -3.01029995663981149813768617048017673474732841360630 dB
2024-04-02 18:17:54.083 [INFO ] [g.openhab.automation.openhab-js.test] - State: 50 %
2024-04-02 18:17:54.086 [INFO ] [g.openhab.automation.openhab-js.test] - Test 4, one appended: 0.5 one
2024-04-02 18:17:55.093 [INFO ] [g.openhab.automation.openhab-js.test] - State: 50 %

This issue has been mentioned on openHAB Community. There might be relevant details there:

https://community.openhab.org/t/inconsistent-percentage-behaviour/154595/36

One suggestion to solve this would be to remove the special handling for unit one in the toFullString() method of QuantityType. That would by default show one behind the value if not overriden with a state description. I think this is acceptable and would at least make it clearer if we see a Number or QuantityType with unit one.