[matter] Report correct Illuminance Measurement Value (#20384)

* [matter] Report correct Illuminance Measurement Value
Fixes #20329

Signed-off-by: Dan Cunningham <dan@digitaldan.com>
This commit is contained in:
Dan Cunningham
2026-03-17 18:43:35 +01:00
committed by GitHub
parent 662f0f72f3
commit 875a60bed8
3 changed files with 34 additions and 13 deletions
@@ -17,15 +17,13 @@ import static org.openhab.binding.matter.internal.MatterBindingConstants.*;
import java.util.Collections;
import java.util.Map;
import javax.measure.quantity.Illuminance;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.matter.internal.client.dto.cluster.gen.IlluminanceMeasurementCluster;
import org.openhab.binding.matter.internal.client.dto.ws.AttributeChangedMessage;
import org.openhab.binding.matter.internal.handler.MatterBaseThingHandler;
import org.openhab.binding.matter.internal.util.ValueUtils;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelGroupUID;
import org.openhab.core.thing.ChannelUID;
@@ -61,8 +59,8 @@ public class IlluminanceMeasurementConverter extends GenericConverter<Illuminanc
switch (message.path.attributeName) {
case IlluminanceMeasurementCluster.ATTRIBUTE_MEASURED_VALUE:
if (message.value instanceof Number number) {
updateState(CHANNEL_ID_ILLUMINANCEMEASURMENT_MEASUREDVALUE,
new QuantityType<Illuminance>(number.intValue(), Units.LUX));
QuantityType<?> lux = ValueUtils.valueToIlluminance(number.intValue());
updateState(CHANNEL_ID_ILLUMINANCEMEASURMENT_MEASUREDVALUE, lux != null ? lux : UnDefType.NULL);
}
break;
}
@@ -71,9 +69,9 @@ public class IlluminanceMeasurementConverter extends GenericConverter<Illuminanc
@Override
public void initState() {
updateState(CHANNEL_ID_ILLUMINANCEMEASURMENT_MEASUREDVALUE,
initializingCluster.measuredValue != null
? new QuantityType<Illuminance>(initializingCluster.measuredValue, Units.LUX)
: UnDefType.NULL);
QuantityType<?> lux = initializingCluster.measuredValue != null
? ValueUtils.valueToIlluminance(initializingCluster.measuredValue)
: null;
updateState(CHANNEL_ID_ILLUMINANCEMEASURMENT_MEASUREDVALUE, lux != null ? lux : UnDefType.NULL);
}
}
@@ -15,6 +15,7 @@ package org.openhab.binding.matter.internal.util;
import java.math.BigDecimal;
import java.math.RoundingMode;
import javax.measure.quantity.Illuminance;
import javax.measure.quantity.Temperature;
import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -23,6 +24,7 @@ import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.ImperialUnits;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.library.unit.Units;
import org.openhab.core.types.Type;
/**
@@ -94,4 +96,23 @@ public class ValueUtils {
public static QuantityType<Temperature> valueToTemperature(int value) {
return new QuantityType<>(BigDecimal.valueOf(value, 2), SIUnits.CELSIUS);
}
/**
* Converts a Matter illuminance measurement value to a {@link QuantityType} in lux.
* The Matter spec encodes illuminance as: MeasuredValue = 10,000 x log10(illuminance) + 1
* A value of 0 indicates illuminance too low to be measured.
*
* @param value the Matter measured value (0 = too low, 1-0xFFFE = encoded illuminance)
* @return the {@link QuantityType} in lux
*/
public static @Nullable QuantityType<Illuminance> valueToIlluminance(int value) {
if (value <= 0) {
return new QuantityType<>(0, Units.LUX);
}
if (value > 0xFFFE) {
return null;
}
double illuminance = Math.pow(10, (value - 1) / 10000.0);
return new QuantityType<>(illuminance, Units.LUX);
}
}
@@ -72,18 +72,20 @@ class IlluminanceMeasurementConverterTest extends BaseMatterConverterTest {
AttributeChangedMessage message = new AttributeChangedMessage();
message.path = new Path();
message.path.attributeName = "measuredValue";
message.value = 100;
message.value = 10001;
converter.onEvent(message);
// 10001 -> 10^((10001-1)/10000) = 10^1 = 10 lux
verify(mockHandler, times(1)).updateState(eq(1), eq("illuminancemeasurement-measuredvalue"),
eq(new QuantityType<Illuminance>(100, Units.LUX)));
eq(new QuantityType<Illuminance>(10.0, Units.LUX)));
}
@Test
void testInitState() {
mockCluster.measuredValue = 100;
mockCluster.measuredValue = 20001;
converter.initState();
// 20001 -> 10^((20001-1)/10000) = 10^2 = 100 lux
verify(mockHandler, times(1)).updateState(eq(1), eq("illuminancemeasurement-measuredvalue"),
eq(new QuantityType<Illuminance>(100, Units.LUX)));
eq(new QuantityType<Illuminance>(100.0, Units.LUX)));
}
@Test