[matter] fixes min/max init of color temp values, adds a few tests as well (#18744)

* [matter] fixes min/max init of color temp values, adds a few tests as well

Signed-off-by: Dan Cunningham <dan@digitaldan.com>
pull/18687/merge
Dan Cunningham 2025-06-02 04:03:51 -07:00 committed by GitHub
parent ac07c60e79
commit 909f2e5e3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 12 deletions

View File

@ -65,23 +65,22 @@ public class ColorControlConverter extends GenericConverter<ColorControlCluster>
private static final int UPDATE_DELAY = 500;
// These are the default values, as well as the min and max limits for the color temperature mireds defined in the
// Matter spec
private static final int MAX_MIREDS = 65279;
private static final int MIN_MIREDS = 1; // this was 0 until matter 1.4
protected static final int MAX_MIREDS = 65279;
protected static final int MIN_MIREDS = 1; // this was 0 until matter 1.4
// These are sane defaults that should be used if the device does not provide a valid range (aka if using default
// MIN / MAX)
private static final int MAX_DEFAULT_MIREDS = 667; // 1500K
private static final int MIN_DEFAULT_MIREDS = 154;
protected static final int MAX_DEFAULT_MIREDS = 667; // 1500K
protected static final int MIN_DEFAULT_MIREDS = 153;
protected boolean supportsHue = false;
protected boolean supportsColorTemperature = false;
protected int colorTempPhysicalMinMireds = 0;
protected int colorTempPhysicalMaxMireds = 0;
private LevelControlCluster.OptionsBitmap levelControlOptionsBitmap = new LevelControlCluster.OptionsBitmap(true,
true);
private boolean lastOnOff = true;
private HSBType lastHSB = new HSBType("0,0,0");
private @Nullable ScheduledFuture<?> colorUpdateTimer = null;
private ScheduledExecutorService colorUpdateScheduler = Executors.newSingleThreadScheduledExecutor();
// Color attributes from the device
private int colorTempPhysicalMinMireds = 0;
private int colorTempPhysicalMaxMireds = 0;
private EnhancedColorModeEnum lastColorMode = EnhancedColorModeEnum.CURRENT_X_AND_CURRENT_Y;
private int lastHue = 0;
private int lastSaturation = 0;
@ -101,13 +100,11 @@ public class ColorControlConverter extends GenericConverter<ColorControlCluster>
// The inovelli device for example sends a max mireds of 65279 (matter spec max value), which means they did not
// actually set the max mireds, but this should never really exceed 667 (1500K)
Integer maxMireds = initializingCluster.colorTempPhysicalMaxMireds;
colorTempPhysicalMaxMireds = (maxMireds == null || maxMireds >= MAX_MIREDS) ? MAX_DEFAULT_MIREDS
: Math.min(maxMireds, MAX_DEFAULT_MIREDS);
colorTempPhysicalMaxMireds = (maxMireds == null || maxMireds >= MAX_MIREDS) ? MAX_DEFAULT_MIREDS : maxMireds;
// the inovelli device for example sends a min mireds of 0 (matter 1.3 default) which means they did not
// actually set the min mireds, but this should never really be less than 154 (6500K)in real life
// actually set the min mireds, but this should never really be less than 153 (6500K) in real life
Integer minMireds = initializingCluster.colorTempPhysicalMinMireds;
colorTempPhysicalMinMireds = (minMireds == null || minMireds <= MIN_MIREDS) ? MIN_DEFAULT_MIREDS
: Math.max(minMireds, MIN_DEFAULT_MIREDS);
colorTempPhysicalMinMireds = (minMireds == null || minMireds <= MIN_MIREDS) ? MIN_DEFAULT_MIREDS : minMireds;
}
@Override

View File

@ -214,4 +214,40 @@ class ColorControlConverterTest extends BaseMatterConverterTest {
// Verify brightness remains 0 since device is off (2 updates, one for onOff, one for level)
verify(mockHandler, times(2)).updateState(eq(1), eq("colorcontrol-color"), eq(new HSBType("180,100,0")));
}
@Test
void testConstructorWithDefaultMaxMireds() {
// Test when maxMireds is null
mockColorCluster.colorTempPhysicalMaxMireds = null;
ColorControlConverter converter = new ColorControlConverter(mockColorCluster, mockHandler, 1, "TestLabel");
assertEquals(667, converter.colorTempPhysicalMaxMireds);
// Test when maxMireds is >= MAX_MIREDS
mockColorCluster.colorTempPhysicalMaxMireds = ColorControlConverter.MAX_MIREDS;
converter = new ColorControlConverter(mockColorCluster, mockHandler, 1, "TestLabel");
assertEquals(ColorControlConverter.MAX_DEFAULT_MIREDS, converter.colorTempPhysicalMaxMireds);
}
@Test
void testConstructorWithDefaultMinMireds() {
// Test when minMireds is null
mockColorCluster.colorTempPhysicalMinMireds = null;
ColorControlConverter converter = new ColorControlConverter(mockColorCluster, mockHandler, 1, "TestLabel");
assertEquals(ColorControlConverter.MIN_DEFAULT_MIREDS, converter.colorTempPhysicalMinMireds);
// Test when minMireds is <= MIN_MIREDS
mockColorCluster.colorTempPhysicalMinMireds = ColorControlConverter.MIN_MIREDS;
converter = new ColorControlConverter(mockColorCluster, mockHandler, 1, "TestLabel");
assertEquals(ColorControlConverter.MIN_DEFAULT_MIREDS, converter.colorTempPhysicalMinMireds);
}
@Test
void testConstructorWithValidMireds() {
// Test with valid values
mockColorCluster.colorTempPhysicalMinMireds = 200;
mockColorCluster.colorTempPhysicalMaxMireds = 400;
ColorControlConverter converter = new ColorControlConverter(mockColorCluster, mockHandler, 1, "TestLabel");
assertEquals(200, converter.colorTempPhysicalMinMireds);
assertEquals(400, converter.colorTempPhysicalMaxMireds);
}
}