[hue] Add semantic tags (#18341)

Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
pull/18683/head
Andrew Fiddian-Green 2025-05-13 20:25:49 +01:00 committed by GitHub
parent 50ce473192
commit 2ab57c6b2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 115 additions and 4 deletions

View File

@ -51,6 +51,7 @@ import org.openhab.binding.hue.internal.api.dto.clip2.ResourceReference;
import org.openhab.binding.hue.internal.api.dto.clip2.Resources; import org.openhab.binding.hue.internal.api.dto.clip2.Resources;
import org.openhab.binding.hue.internal.api.dto.clip2.TimedEffects; import org.openhab.binding.hue.internal.api.dto.clip2.TimedEffects;
import org.openhab.binding.hue.internal.api.dto.clip2.enums.ActionType; import org.openhab.binding.hue.internal.api.dto.clip2.enums.ActionType;
import org.openhab.binding.hue.internal.api.dto.clip2.enums.Archetype;
import org.openhab.binding.hue.internal.api.dto.clip2.enums.ContentType; import org.openhab.binding.hue.internal.api.dto.clip2.enums.ContentType;
import org.openhab.binding.hue.internal.api.dto.clip2.enums.EffectType; import org.openhab.binding.hue.internal.api.dto.clip2.enums.EffectType;
import org.openhab.binding.hue.internal.api.dto.clip2.enums.ResourceType; import org.openhab.binding.hue.internal.api.dto.clip2.enums.ResourceType;
@ -71,6 +72,8 @@ import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType; import org.openhab.core.library.types.StringType;
import org.openhab.core.library.unit.MetricPrefix; import org.openhab.core.library.unit.MetricPrefix;
import org.openhab.core.library.unit.Units; import org.openhab.core.library.unit.Units;
import org.openhab.core.semantics.SemanticTag;
import org.openhab.core.semantics.model.DefaultSemanticTags.Equipment;
import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Channel; import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
@ -109,6 +112,9 @@ public class Clip2ThingHandler extends BaseThingHandler {
private static final Set<ResourceType> SUPPORTED_SCENE_TYPES = Set.of(ResourceType.SCENE, ResourceType.SMART_SCENE); private static final Set<ResourceType> SUPPORTED_SCENE_TYPES = Set.of(ResourceType.SCENE, ResourceType.SMART_SCENE);
private static final Set<Archetype> STRIPLIGHT_ARCHETYPES = Set.of(Archetype.HUE_LIGHTSTRIP,
Archetype.HUE_LIGHTSTRIP_TV, Archetype.HUE_TUBE, Archetype.STRING_LIGHT, Archetype.CHRISTMAS_TREE);
private static final Duration DYNAMICS_ACTIVE_WINDOW = Duration.ofSeconds(10); private static final Duration DYNAMICS_ACTIVE_WINDOW = Duration.ofSeconds(10);
private static final String LK_WISER_DIMMER_MODEL_ID = "LK Dimmer"; private static final String LK_WISER_DIMMER_MODEL_ID = "LK Dimmer";
@ -1069,6 +1075,7 @@ public class Clip2ThingHandler extends BaseThingHandler {
updateServiceContributors(); updateServiceContributors();
updateChannelList(); updateChannelList();
updateChannelItemLinksFromLegacy(); updateChannelItemLinksFromLegacy();
updateEquipmentTag();
if (!hasConnectivityIssue) { if (!hasConnectivityIssue) {
updateStatus(ThingStatus.ONLINE); updateStatus(ThingStatus.ONLINE);
} }
@ -1411,4 +1418,54 @@ public class Clip2ThingHandler extends BaseThingHandler {
} }
} }
} }
/**
* Update the thing's semantic equipment tag. The main determinant for the equipment type is the supported channels.
* For lights use the product archetype to split between light bulbs and strip lights. Rooms and Zones are
* considered to be zones.
*/
private void updateEquipmentTag() {
if (!disposing) {
int sensorCount = 0;
SemanticTag equipmentTag = null;
if (Set.of(ResourceType.ROOM, ResourceType.ZONE).contains(thisResource.getType())) {
equipmentTag = Equipment.ZONE;
}
if ((thing.getChannel(CHANNEL_2_COLOR) != null) || (thing.getChannel(CHANNEL_2_BRIGHTNESS) != null)
|| (thing.getChannel(CHANNEL_2_SWITCH) != null)) {
equipmentTag = (thisResource.getProductData() instanceof ProductData productData)
&& STRIPLIGHT_ARCHETYPES.contains(productData.getProductArchetype()) ? Equipment.LIGHT_STRIP
: Equipment.LIGHTBULB;
}
if (thing.getChannel(CHANNEL_2_BUTTON_LAST_EVENT) != null) {
equipmentTag = Equipment.BUTTON;
}
if (thing.getChannel(CHANNEL_2_ROTARY_STEPS) != null) {
equipmentTag = Equipment.DIAL;
}
if (thing.getChannel(CHANNEL_2_SECURITY_CONTACT) != null) {
equipmentTag = Equipment.CONTACT_SENSOR;
}
if (thing.getChannel(CHANNEL_2_MOTION) != null) {
sensorCount++;
equipmentTag = Equipment.MOTION_DETECTOR;
}
if (thing.getChannel(CHANNEL_2_LIGHT_LEVEL) != null) {
sensorCount++;
equipmentTag = Equipment.ILLUMINANCE_SENSOR;
}
if (thing.getChannel(CHANNEL_2_TEMPERATURE) != null) {
sensorCount++;
equipmentTag = Equipment.TEMPERATURE_SENSOR;
}
if (sensorCount > 1) {
equipmentTag = Equipment.SENSOR;
}
if (equipmentTag != null) {
logger.debug("{} -> updateEquipmentTag({})", resourceId, equipmentTag.getName());
updateThing(editThing().withSemanticEquipmentTag(equipmentTag).build());
}
}
}
} }

View File

@ -66,6 +66,7 @@
<bridge-type id="bridge-api2"> <bridge-type id="bridge-api2">
<label>Hue API v2 Bridge</label> <label>Hue API v2 Bridge</label>
<description>The Hue Bridge represents a Philips Hue Bridge supporting API v2.</description> <description>The Hue Bridge represents a Philips Hue Bridge supporting API v2.</description>
<semantic-equipment-tag>NetworkAppliance</semantic-equipment-tag>
<channel-groups> <channel-groups>
<channel-group id="automation" typeId="automation"/> <channel-group id="automation" typeId="automation"/>

View File

@ -8,6 +8,10 @@
<label>Last Updated</label> <label>Last Updated</label>
<description>The date and time when the sensor was last updated.</description> <description>The date and time when the sensor was last updated.</description>
<category>Time</category> <category>Time</category>
<tags>
<tag>Status</tag>
<tag>Timestamp</tag>
</tags>
<state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/> <state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
</channel-type> </channel-type>
@ -17,7 +21,7 @@
<description>Current illuminance.</description> <description>Current illuminance.</description>
<tags> <tags>
<tag>Measurement</tag> <tag>Measurement</tag>
<tag>Light</tag> <tag>Illuminance</tag>
</tags> </tags>
<state readOnly="true" pattern="%.1f %unit%"/> <state readOnly="true" pattern="%.1f %unit%"/>
</channel-type> </channel-type>
@ -26,6 +30,10 @@
<item-type>Number</item-type> <item-type>Number</item-type>
<label>Light Level</label> <label>Light Level</label>
<description>Current light level.</description> <description>Current light level.</description>
<tags>
<tag>Measurement</tag>
<tag>Illuminance</tag>
</tags>
<state readOnly="true" pattern="%d"/> <state readOnly="true" pattern="%d"/>
</channel-type> </channel-type>
@ -142,7 +150,8 @@
<label>Alert</label> <label>Alert</label>
<description>The alert channel allows a temporary change to the bulbs state.</description> <description>The alert channel allows a temporary change to the bulbs state.</description>
<tags> <tags>
<tag>Alarm</tag> <tag>Switch</tag>
<tag>Mode</tag>
</tags> </tags>
<state> <state>
<options> <options>
@ -159,6 +168,10 @@
<label>Color Loop</label> <label>Color Loop</label>
<description>The effect channel allows putting the bulb in a color looping mode.</description> <description>The effect channel allows putting the bulb in a color looping mode.</description>
<category>ColorLight</category> <category>ColorLight</category>
<tags>
<tag>Switch</tag>
<tag>Mode</tag>
</tags>
</channel-type> </channel-type>
<!-- CLIP Sensor --> <!-- CLIP Sensor -->
@ -179,6 +192,10 @@
<item-type>String</item-type> <item-type>String</item-type>
<label>Scene</label> <label>Scene</label>
<description>The scene channel allows recalling a scene to all lights that belong to the scene.</description> <description>The scene channel allows recalling a scene to all lights that belong to the scene.</description>
<tags>
<tag>Control</tag>
<tag>Mode</tag>
</tags>
</channel-type> </channel-type>
<!-- API v2 Channel Types --> <!-- API v2 Channel Types -->
@ -200,12 +217,20 @@
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Sensor Enabled</label> <label>Sensor Enabled</label>
<category>Lock</category> <category>Lock</category>
<tags>
<tag>Switch</tag>
<tag>Mode</tag>
</tags>
</channel-type> </channel-type>
<channel-type id="scene-v2" advanced="true"> <channel-type id="scene-v2" advanced="true">
<item-type>String</item-type> <item-type>String</item-type>
<label>Scene</label> <label>Scene</label>
<category>MediaControl</category> <category>MediaControl</category>
<tags>
<tag>Control</tag>
<tag>Mode</tag>
</tags>
<state pattern="%s"/> <state pattern="%s"/>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
@ -215,12 +240,20 @@
<label>Last Updated</label> <label>Last Updated</label>
<description>The date and time when the thing was last updated.</description> <description>The date and time when the thing was last updated.</description>
<category>Time</category> <category>Time</category>
<tags>
<tag>Status</tag>
<tag>Timestamp</tag>
</tags>
<state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/> <state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
</channel-type> </channel-type>
<channel-type id="alert-v2" advanced="true"> <channel-type id="alert-v2" advanced="true">
<item-type>String</item-type> <item-type>String</item-type>
<label>Alert</label> <label>Alert</label>
<tags>
<tag>Control</tag>
<tag>Mode</tag>
</tags>
<state pattern="%s"/> <state pattern="%s"/>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
@ -228,6 +261,10 @@
<channel-type id="effect-v2" advanced="true"> <channel-type id="effect-v2" advanced="true">
<item-type>String</item-type> <item-type>String</item-type>
<label>Effect</label> <label>Effect</label>
<tags>
<tag>Control</tag>
<tag>Mode</tag>
</tags>
<state pattern="%s"/> <state pattern="%s"/>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
@ -237,6 +274,10 @@
<label>Dynamics</label> <label>Dynamics</label>
<description>The duration (ms) of dynamic transitions between light or scene states.</description> <description>The duration (ms) of dynamic transitions between light or scene states.</description>
<category>Time</category> <category>Time</category>
<tags>
<tag>Control</tag>
<tag>Duration</tag>
</tags>
<state min="0" step="100" pattern="%d ms"/> <state min="0" step="100" pattern="%d ms"/>
</channel-type> </channel-type>
@ -247,7 +288,7 @@
<category>ColorLight</category> <category>ColorLight</category>
<tags> <tags>
<tag>Control</tag> <tag>Control</tag>
<tag>Light</tag> <tag>Color</tag>
</tags> </tags>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
</channel-type> </channel-type>
@ -259,7 +300,7 @@
<category>Light</category> <category>Light</category>
<tags> <tags>
<tag>Control</tag> <tag>Control</tag>
<tag>Light</tag> <tag>Brightness</tag>
</tags> </tags>
<state min="0" max="100" pattern="%.1f %%"/> <state min="0" max="100" pattern="%.1f %%"/>
<autoUpdatePolicy>veto</autoUpdatePolicy> <autoUpdatePolicy>veto</autoUpdatePolicy>
@ -281,18 +322,30 @@
<item-type>Contact</item-type> <item-type>Contact</item-type>
<label>Open/Closed</label> <label>Open/Closed</label>
<category>Lock</category> <category>Lock</category>
<tags>
<tag>Alarm</tag>
<tag>OpenState</tag>
</tags>
</channel-type> </channel-type>
<channel-type id="security-tamper"> <channel-type id="security-tamper">
<item-type>Contact</item-type> <item-type>Contact</item-type>
<label>Normal/Tamper</label> <label>Normal/Tamper</label>
<category>Siren</category> <category>Siren</category>
<tags>
<tag>Alarm</tag>
<tag>Tampered</tag>
</tags>
</channel-type> </channel-type>
<channel-type id="automation-enable"> <channel-type id="automation-enable">
<item-type>Switch</item-type> <item-type>Switch</item-type>
<label>Enable</label> <label>Enable</label>
<category>Switch</category> <category>Switch</category>
<tags>
<tag>Switch</tag>
<tag>Enabled</tag>
</tags>
</channel-type> </channel-type>
<channel-group-type id="automation"> <channel-group-type id="automation">