public enum TraitUnit
- Object
- Enum<TraitUnit>
- TraitUnit
ImplementsComparable<TraitUnit>
A unit of measure for a Trait value.
Conversion is affine, with one honest exception
canonical = value * scale + offset, the same model
com.codename1.health.HealthUnit uses, because temperature needs the
offset. Converting between units of different
TraitUnitDimensions throws IllegalArgumentException: that is a bug in
the calling code, not a condition to report through an AsyncResource.
Mireds and Kelvin are reciprocal, not affine, so Kelvin is deliberately
not a constant here – it cannot be expressed in the table, and forcing it
in would produce a colour temperature that is silently wrong rather than
obviously wrong. Use miredToKelvin(double) and
kelvinToMired(double), or TraitValue.getColorTemperatureKelvin(),
which are named so that stepping outside the conversion table is a visible
act.
And the trap that catches everyone once: a higher mired value is a warmer light, because mireds are the reciprocal of Kelvin. 153 mireds is a cold blue-white; 400 is candlelight.
Why this is an enum where HealthUnit is a class
HealthUnit is an interned final class because its symbol is the wire
format Apple’s HKUnit(from:) parses, and because the set grows with the
data types. Neither is true here: the set is small, closed and defined by
what the two backends can actually express, and nothing about a home
accessory will need a unit that is not already on this list. An enum gets
switch and exhaustive reasoning for free.
The one thing an enum does not get for free is a stable wire form –
ordinal() shifts the moment a constant is inserted in the middle – so
each carries an explicit getWireId() and forWireId(int) resolves it.
Enum constants
NONE | No unit: an ordinal, a count, a plain number. |
PERCENT | Percent, 0 to 100. |
CELSIUS | Degrees Celsius. |
FAHRENHEIT | Degrees Fahrenheit. |
ARC_DEGREE | Degrees of arc, 0 to 360. |
MIRED | Mireds – micro reciprocal degrees, the reciprocal of colour temperature in Kelvin scaled by a million. |
LUX | Lux. |
PPM | Parts per million. |
PPB | Parts per billion. |
MICROGRAM_PER_CUBIC_METER | Micrograms per cubic metre. |
Methods
public static TraitUnit[] values() | |
public static TraitUnit valueOf(String name) | |
public int getWireId() | The stable identifier this unit crosses the native boundary as. |
public TraitUnitDimension getDimension() | What this unit measures. |
public boolean isCompatibleWith(TraitUnit other) | Whether a value in this unit can be converted into the supplied one. |
public static double convert(double value, TraitUnit from, TraitUnit to) | Converts a value between two units of the same dimension. |
public static TraitUnit forWireId(int wireId) | Resolves a unit by its wire identifier, total: an unrecognized id answers null rather than throwing, so a value from a newer port degrades to “no value” instead of taking down the decode. |
public static double miredToKelvin(double mireds) | Converts mireds to Kelvin. |
public static double kelvinToMired(double kelvin) | Converts Kelvin to mireds. |
Inherited methods
Enum constant details
NONE
NONETraitUnitDimension.DIMENSIONLESS.PERCENT
PERCENTPercent, 0 to 100. The canonical unit of
TraitUnitDimension.RATIO, and the unit of every proportion in this
API – brightness, saturation, covering position, fan speed, battery
level, humidity.
Both backends carry these as scaled integers with different scales (Matter’s level control is 0 to 254, its covering position is 0 to 10000, its battery percentage is in halves) and every one of those conversions happens inside the port. Application code sees percent.
CELSIUS
CELSIUSTraitUnitDimension.TEMPERATURE.FAHRENHEIT
FAHRENHEITARC_DEGREE
ARC_DEGREETraitUnitDimension.ANGLE, used for colour hue.MIRED
MIREDMireds – micro reciprocal degrees, the reciprocal of colour
temperature in Kelvin scaled by a million. The canonical unit of
TraitUnitDimension.COLOR_TEMPERATURE.
Chosen over Kelvin because it is what both platforms use natively:
HomeKit’s HMCharacteristicTypeColorTemperature is in mireds and
Matter’s ColorTemperatureMireds is in mireds. Making Kelvin
canonical would mean a reciprocal on every read and every write, in
both ports, for no gain.
LUX
LUXTraitUnitDimension.ILLUMINANCE.PPM
PPMTraitUnitDimension.CONCENTRATION_PARTS.PPB
PPBMICROGRAM_PER_CUBIC_METER
MICROGRAM_PER_CUBIC_METERTraitUnitDimension.CONCENTRATION_MASS, used for particulate matter.Method details
values
public static TraitUnit[] values()valueOf
public static TraitUnit valueOf(String name)getWireId
public int getWireId()The stable identifier this unit crosses the native boundary as.
Fixed per constant and never reused, so inserting a unit into the middle of this list cannot silently re-label values a port already sends.
Returns
getDimension
public TraitUnitDimension getDimension()Returns
nullisCompatibleWith
public boolean isCompatibleWith(TraitUnit other)Parameters
otherTraitUnit- the target unit, or
null
Returns
true when both measure the same dimensionconvert
public static double convert(double value, TraitUnit from, TraitUnit to)Parameters
valuedouble- the quantity to convert
fromTraitUnit- the unit
valueis expressed in toTraitUnit- the unit to express it in
Returns
Throws
IllegalArgumentException- when either unit is
nullor they measure different dimensions
forWireId
public static TraitUnit forWireId(int wireId)null rather than throwing, so a value from a newer port
degrades to “no value” instead of taking down the decode.Parameters
wireIdint- an identifier previously returned by
getWireId()
Returns
nullmiredToKelvin
public static double miredToKelvin(double mireds)Converts mireds to Kelvin.
Outside the convert(double, TraitUnit, TraitUnit) table on purpose:
the relationship is reciprocal, and an affine table that pretended
otherwise would return a plausible number that is wrong everywhere
except at one point.
Parameters
miredsdouble- a colour temperature in mireds; must be greater than zero
Returns
Throws
IllegalArgumentException- when
miredsis zero, negative or not a number
kelvinToMired
public static double kelvinToMired(double kelvin)miredToKelvin(double) for why this
is a named method rather than a table entry.Parameters
kelvindouble- a colour temperature in Kelvin; must be greater than zero
Returns
Throws
IllegalArgumentException- when
kelvinis zero, negative or not a number