smarthome icon indicating copy to clipboard operation
smarthome copied to clipboard

QuantityType: define unit for min, max, step in channel state description

Open htreu opened this issue 7 years ago • 15 comments

As mentioned in this comment https://github.com/eclipse/smarthome/issues/5243#issuecomment-385268489 its currently not possible to define a unit for a channel's state description min, max and step values.

htreu avatar May 07 '18 06:05 htreu

As tested on PaperUI with the current Homematic binding, if you're using °F on a thermostat, you are limited to the range [4.5..30.5]°F which is actually pretty cold for heating ;-)

The root cause is that from the state description, it is uncertain in which unit the boundaries are expressed. I think there is different ways how to deal with that:

  1. Use the unit of your boundary inside the state definition (e.g. min="4.5°C" max="30.5°C" step="0.1°C")
  2. Leave the min/max/step as it is but introduce an additional attribute inside the state, like minMaxStepUnit="°C"
  3. other ideas?

mdicke2s avatar Dec 07 '18 12:12 mdicke2s

@mdicke2s I would opt for minMaxStepUnit. Otherwise the min/,ax values would be strings and could not easily be used for comparison.

afuechsel avatar Jan 08 '19 13:01 afuechsel

From readability, I like min="4.5°C" max="30.5°C" step="0.1°C" more. However, it has two drawbacks

  1. all three attributes must be parsed as string
  2. users may do very complicated stuff like unit="K" min="4.5°C" max="30.5°F" step="0.1°C"

Therefore I would also prefer minMaxStepUnit="°C"

mdicke2s avatar Jan 08 '19 14:01 mdicke2s

minMaxStepUnit makes sense to me as the three values are always in direct relation and thus should not have different units. The question is whether we are always fine with converting them to a different unit, which might mean that we have min=34.2455°F, max=104.5343 and step=1.6754°F for a US user. Or might we want to be able to define min/max/step for multiple units in the config description and only convert them for units that are not specifically provided?

kaikreuzer avatar Jan 08 '19 14:01 kaikreuzer

For simplicity I would go with always converting the values but looking at the broken values it might be better and more user friendly to have different min/max/step values per unit...

afuechsel avatar Jan 08 '19 14:01 afuechsel

Mhhh, I do not get why we expect binding developers to use such weird numbers. I would assume that raw data that is transferred, will always be in a common unit (or potentially divided/multiplied by a multiple of 10). Then it would be self-evident to use that unit for min/max/step. If the raw data unit however is not ideally for UIs, one may define unit different than minMaxStepUnit and the UI may deal with conversion & rounding of boundaries.

I fear if we define different min/max/step per unit, its definition get's more complicated.

mdicke2s avatar Jan 08 '19 15:01 mdicke2s

Mhhh, I do not get why we expect binding developers to use such weird numbers.

My example was a situation where the binding developer provides min/max/step in Celsius, but the user runs his system (and as such his sliders in the UI) in Fahrenheit - you will end up with such "weird numbers" when simply automatically converting them.

kaikreuzer avatar Jan 08 '19 15:01 kaikreuzer

How is the conversion of the „step“ calculated? For most units this is a simple proportional relationship and the unit conversion of the step value will be correct. If offsets are part of the conversion that will fail (most obvious is Celsius/Fahrenheit, where the simple conversion of 1degC will be converted to 33.8 degF which is obviously wrong). A solution might be to calculate the number-of-steps = (max-min)/step, convert max and min and then calculate step=(max-min)/number-of-steps.

J-N-K avatar Jan 08 '19 19:01 J-N-K

@J-N-K well, from my POV step calculation would be just as simple as taking the offset into account. So a step of 1°C would be 33,8°F - 32 = 1,8°F.

afuechsel avatar Jan 09 '19 07:01 afuechsel

I agree with @afuechsel. We have to distinguish between absolute temperature conversion (fahrenheit_temperature=9*celsius_temperature/5+32) and temperature difference conversion (delta_fahrenheit=9*delta_celsius/5). BTW: We recently had a similar topic, compare SystemOffsetProfile.

Let's complete the example by sketching the situation for a thermostat. Let's say it has the following specification:

TYPE RAW(8-bit integer) RAW+50 °C °F
MIN 0 50 5.0 41.00
some valid value 114 164 16.4 61.52
MAX 250 300 30.0 86.00
STEP 1 - 0.1 0.18

I think for this case the state definition <state min="5.0" max="30.0" step="0.1" pattern="%.2f %unit%" readOnly="false" minMaxStepUnit=°C"> would be sufficient. The framework may calculate fahrenheit boundaries itself and since the fahrenheit step is 0.18 , 2 decimal precision will allways be enough.

However, I can imagine another case which gets more complicated. Let's say there is a pointing device that accepts an angle (e.g. to 90° with step of ) as input. Expressing that in radians would be 0 to 0.5π with step of π/180. If the user wants to apply the maximum value using radians, it is required to round the approximation correctly.

mdicke2s avatar Jan 09 '19 08:01 mdicke2s

We have to think about min/max/step and appropriate unit(s) from the users perspective: When operating the thermostat in the US the user also does expect to have a 0.1°F granularity for control. And for the angle example the binding developer should also use min/max/step values and unit which are acceptable for the user. Even when the device needs radiant values the input from the UI should be in degrees. So I second @kaikreuzer's request/idea to have separate values and unit pairs. This is unfortunately not very compatible with the XML format we have right now. Maybe we can introduce a default mapping which indicates how to map the given step value to another compatible unit? Like 0.1°C -> 0.1°F. wdyt?

htreu avatar Jan 10 '19 08:01 htreu

I have the feeling that a mapping table will not get us that far... We would have to maintain a clunky list and are left with a solution which may not provide the accuracy and flexibility we actually need. Here is another approach which @mdicke2s and me discussed offline:

We could extend the <state> entity by a unit attribute which defines the unit for min/max/step (this would be the "defaiult case"). For additional units and on top: for additional patterns! we would have an optional list of ext-state entities for which the unit attribute would serve as a key and whenever the UI/user is on a different locale then the default unit suggests we could look up the ext-state entity with the appropriate unit.

Example XML:

<state min="5.0" max="30.0" step="0.1" unit="°C" pattern="%.1f %unit%">
    <ext-states> <!-- optional list of extended state definitions -->
	    <ext-state min="41.00" max="86.00" step="0.25" unit="°F" pattern="%.2f %unit%" />
	    <ext-state min="278" max="308" step="1" unit="K" pattern="%d kelvin" />
    </ext-states>
</state>

Note: The "kelvin" entry will not map to any locale, but a UI described from the sitemap domain may also request a specific unit. Then the pattern & min/max/step values would be picked up from the ext-state list.

edit: typo fixed.

htreu avatar Jan 17 '19 07:01 htreu

And what would happen, if the requested unit is not on the list ext-state? Will it be converted? BTW:, there is a typo in your example: "ext-sate"

afuechsel avatar Jan 17 '19 09:01 afuechsel

if the requested unit is not on the list ext-state?

It would be converted. In this case the afore mentioned mapping table would actually also help.

htreu avatar Jan 17 '19 14:01 htreu

An alternative might be to modify the xml schema to allow more than one state element..

<state min=15 max=30 step=0.5 unit="°C" ..>
<state min=60 max=90 step=1 unit="°F" ..>

andrewfg avatar May 02 '20 19:05 andrewfg