Semantic Tags: set EQUIPMENT tags on Things (#4617)

Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
Co-authored-by: Holger Friedrich <mail@holger-friedrich.de>
pull/4667/head
Andrew Fiddian-Green 2025-04-03 20:10:13 +01:00 committed by GitHub
parent 1c33c03cd4
commit 85d539c35b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 251 additions and 42 deletions

View File

@ -140,6 +140,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
* @author Dimitar Ivanov - replaced Firmware UID with thing UID and firmware version
* @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@Component
@JaxrsResource
@ -326,14 +327,15 @@ public class ThingResource implements RESTResource {
lastModified = Date.from(Instant.now().truncatedTo(ChronoUnit.SECONDS));
}
thingStream = dtoMapper.limitToFields(thingStream, "UID,label,bridgeUID,thingTypeUID,location,editable");
thingStream = dtoMapper.limitToFields(thingStream,
"UID,label,bridgeUID,thingTypeUID,location,editable,semanticEquipmentTag");
return Response.ok(new Stream2JSONInputStream(thingStream)).lastModified(lastModified)
.cacheControl(RESTConstants.CACHE_CONTROL).build();
}
if (summary != null && summary) {
thingStream = dtoMapper.limitToFields(thingStream,
"UID,label,bridgeUID,thingTypeUID,statusInfo,firmwareStatus,location,editable");
"UID,label,bridgeUID,thingTypeUID,statusInfo,firmwareStatus,location,editable,semanticEquipmentTag");
}
return Response.ok(new Stream2JSONInputStream(thingStream)).build();
}

View File

@ -90,6 +90,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
* @author Yannick Schaus - Added filter to getAll
* @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@Component
@JaxrsResource
@ -188,7 +189,7 @@ public class ThingTypeResource implements RESTResource {
thingType.getCategory(), thingType.isListed(), parameters, channelDefinitions,
convertToChannelGroupDefinitionDTOs(thingType.getChannelGroupDefinitions(), locale),
thingType.getSupportedBridgeTypeUIDs(), thingType.getProperties(), thingType instanceof BridgeType,
parameterGroups, thingType.getExtensibleChannelTypeIds());
parameterGroups, thingType.getExtensibleChannelTypeIds(), thingType.getSemanticEquipmentTag());
}
private List<ChannelGroupDefinitionDTO> convertToChannelGroupDefinitionDTOs(

View File

@ -26,6 +26,7 @@ import org.openhab.core.thing.firmware.dto.FirmwareStatusDTO;
* @author Kai Kreuzer - Removed links and items
* @author Chris Jackson - Added 'editable' flag
* @author Wouter Born - Let (Enriched)ThingDTO extend AbstractThingDTO so both can define their own "channels" type
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
public class EnrichedThingDTO extends AbstractThingDTO {
@ -46,7 +47,7 @@ public class EnrichedThingDTO extends AbstractThingDTO {
EnrichedThingDTO(ThingDTO thingDTO, List<EnrichedChannelDTO> channels, ThingStatusInfo statusInfo,
FirmwareStatusDTO firmwareStatus, boolean editable) {
super(thingDTO.thingTypeUID, thingDTO.UID, thingDTO.label, thingDTO.bridgeUID, thingDTO.configuration,
thingDTO.properties, thingDTO.location);
thingDTO.properties, thingDTO.location, thingDTO.semanticEquipmentTag);
this.channels = channels;
this.statusInfo = statusInfo;
this.firmwareStatus = firmwareStatus;

View File

@ -23,6 +23,9 @@
<jaxb:bindings node="//xs:simpleType[@name='semanticPropertyOrPointTag']">
<jaxb:typesafeEnumClass map="false"/>
</jaxb:bindings>
<jaxb:bindings node="//xs:simpleType[@name='semanticEquipmentTag']">
<jaxb:typesafeEnumClass map="false"/>
</jaxb:bindings>
</jaxb:bindings>
<jaxb:bindings schemaLocation="../update/update-description-1.0.0.xsd">

View File

@ -26,6 +26,7 @@
<xs:element name="label" type="xs:string"/>
<xs:element name="description" type="xs:string" minOccurs="0"/>
<xs:element name="category" type="xs:string" minOccurs="0"/>
<xs:element name="semantic-equipment-tag" type="thing-description:semanticEquipmentTag" minOccurs="0"/>
<xs:choice minOccurs="0">
<xs:element name="channels" type="thing-description:channels"/>
<xs:element name="channel-groups" type="thing-description:channelGroups"/>
@ -293,7 +294,7 @@
<xs:enumeration value="Current"/>
<xs:enumeration value="Frequency"/>
<xs:enumeration value="Gas"/>
<xs:enumeration value="Application"/>
<xs:enumeration value="App"/>
<xs:enumeration value="Channel"/>
<xs:enumeration value="Mode"/>
<xs:enumeration value="SoundVolume"/>
@ -321,4 +322,64 @@
<!-- End Allowed Semantic Point Tag Values -->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="semanticEquipmentTag">
<xs:restriction base="xs:string">
<!-- Begin Allowed Semantic Equipment Tag Values -->
<xs:enumeration value="AlarmSystem"/>
<xs:enumeration value="Battery"/>
<xs:enumeration value="Blinds"/>
<xs:enumeration value="Boiler"/>
<xs:enumeration value="Camera"/>
<xs:enumeration value="Car"/>
<xs:enumeration value="CleaningRobot"/>
<xs:enumeration value="Door"/>
<xs:enumeration value="BackDoor"/>
<xs:enumeration value="CellarDoor"/>
<xs:enumeration value="FrontDoor"/>
<xs:enumeration value="GarageDoor"/>
<xs:enumeration value="Gate"/>
<xs:enumeration value="InnerDoor"/>
<xs:enumeration value="SideDoor"/>
<xs:enumeration value="Doorbell"/>
<xs:enumeration value="Fan"/>
<xs:enumeration value="CeilingFan"/>
<xs:enumeration value="KitchenHood"/>
<xs:enumeration value="HVAC"/>
<xs:enumeration value="Inverter"/>
<xs:enumeration value="LawnMower"/>
<xs:enumeration value="Lightbulb"/>
<xs:enumeration value="LightStripe"/>
<xs:enumeration value="Lock"/>
<xs:enumeration value="NetworkAppliance"/>
<xs:enumeration value="PowerOutlet"/>
<xs:enumeration value="Projector"/>
<xs:enumeration value="Pump"/>
<xs:enumeration value="RadiatorControl"/>
<xs:enumeration value="Receiver"/>
<xs:enumeration value="RemoteControl"/>
<xs:enumeration value="Screen"/>
<xs:enumeration value="Television"/>
<xs:enumeration value="Sensor"/>
<xs:enumeration value="MotionDetector"/>
<xs:enumeration value="SmokeDetector"/>
<xs:enumeration value="Siren"/>
<xs:enumeration value="Smartphone"/>
<xs:enumeration value="Speaker"/>
<xs:enumeration value="Valve"/>
<xs:enumeration value="VoiceAssistant"/>
<xs:enumeration value="WallSwitch"/>
<xs:enumeration value="WebService"/>
<xs:enumeration value="WeatherService"/>
<xs:enumeration value="WhiteGood"/>
<xs:enumeration value="Dishwasher"/>
<xs:enumeration value="Dryer"/>
<xs:enumeration value="Freezer"/>
<xs:enumeration value="Oven"/>
<xs:enumeration value="Refrigerator"/>
<xs:enumeration value="WashingMachine"/>
<xs:enumeration value="Window"/>
<!-- End Allowed Semantic Equipment Tag Values -->
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@ -35,6 +35,7 @@ import org.openhab.core.thing.binding.ThingHandler;
* @author Kai Kreuzer - Removed linked items from Thing
* @author Yordan Zhelev - Added method for getting the enabled status
* @author Christoph Weitkamp - Added method {@code getChannel(ChannelUID)}
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public interface Thing extends Identifiable<ThingUID> {
@ -230,4 +231,19 @@ public interface Thing extends Identifiable<ThingUID> {
* @return Returns {@code true} if the thing is enabled. Return {@code false} otherwise.
*/
boolean isEnabled();
/**
* Get the semantic (equipment) tag of the {@link Thing}.
*
* @return the semantic (equipment) tag or {@code null} if no tag has been configured.
*/
@Nullable
String getSemanticEquipmentTag();
/**
* Set the semantic (equipment) tag of the {@link Thing}.
*
* @param semanticEquipmentTag the semantic (equipment) tag or {@code null} if no tag has been configured.
*/
void setSemanticEquipmentTag(@Nullable String semanticEquipmentTag);
}

View File

@ -59,6 +59,7 @@ import org.openhab.core.types.StateOption;
* persist those for future thing initializations
*
* @author Jan N. Klug - Initial contribution
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public abstract class AbstractStorageBasedTypeProvider
@ -395,6 +396,7 @@ public abstract class AbstractStorageBasedTypeProvider
public Map<String, String> properties = Map.of();
public boolean isListed = false;
public boolean isBridge = false;
public @Nullable String semanticEquipmentTag;
}
static class ChannelDefinitionEntity {

View File

@ -26,6 +26,7 @@ import org.openhab.core.thing.binding.builder.BridgeBuilder;
*
* @author Dennis Nobel - Initial contribution
* @author Stefan Bußweiler - Added implementation of BridgeHandler interface
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public abstract class BaseBridgeHandler extends BaseThingHandler implements BridgeHandler {
@ -52,7 +53,8 @@ public abstract class BaseBridgeHandler extends BaseThingHandler implements Brid
protected BridgeBuilder editThing() {
return BridgeBuilder.create(thing.getThingTypeUID(), thing.getUID()).withBridge(thing.getBridgeUID())
.withChannels(thing.getChannels()).withConfiguration(thing.getConfiguration())
.withLabel(thing.getLabel()).withLocation(thing.getLocation()).withProperties(thing.getProperties());
.withLabel(thing.getLabel()).withLocation(thing.getLocation()).withProperties(thing.getProperties())
.withSemanticEquipmentTag(thing.getSemanticEquipmentTag());
}
@Override

View File

@ -62,6 +62,7 @@ import org.slf4j.LoggerFactory;
* @author Kai Kreuzer - Refactored isLinked method to not use deprecated functions anymore
* @author Christoph Weitkamp - Moved OSGI ServiceTracker from BaseThingHandler to ThingHandlerCallback
* @author Jan N. Klug - added time series support
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public abstract class BaseThingHandler implements ThingHandler {
@ -446,7 +447,8 @@ public abstract class BaseThingHandler implements ThingHandler {
return ThingBuilder.create(this.thing.getThingTypeUID(), this.thing.getUID())
.withBridge(this.thing.getBridgeUID()).withChannels(this.thing.getChannels())
.withConfiguration(this.thing.getConfiguration()).withLabel(this.thing.getLabel())
.withLocation(this.thing.getLocation()).withProperties(this.thing.getProperties());
.withLocation(this.thing.getLocation()).withProperties(this.thing.getProperties())
.withSemanticEquipmentTag(this.thing.getSemanticEquipmentTag());
}
/**

View File

@ -41,6 +41,7 @@ import org.slf4j.LoggerFactory;
* values
* @author Thomas Höfer - added thing and thing type properties
* @author Chris Jackson - Added properties, label, description
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class ThingFactory {
@ -91,7 +92,8 @@ public class ThingFactory {
List<Channel> channels = ThingFactoryHelper.createChannels(thingType, thingUID, configDescriptionRegistry);
return createThingBuilder(thingType, thingUID).withConfiguration(configuration).withChannels(channels)
.withProperties(thingType.getProperties()).withBridge(bridgeUID).build();
.withProperties(thingType.getProperties()).withBridge(bridgeUID)
.withSemanticEquipmentTag(thingType.getSemanticEquipmentTag()).build();
}
public static @Nullable Thing createThing(ThingUID thingUID, Configuration configuration,

View File

@ -31,6 +31,7 @@ import org.openhab.core.thing.internal.BridgeImpl;
* @author Dennis Nobel - Initial contribution
* @author Kai Kreuzer - Refactoring to make BridgeBuilder a subclass of ThingBuilder
* @author Markus Rathgeb - Override methods to return BridgeBuidler instead of ThingBuidler
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class BridgeBuilder extends ThingBuilder {
@ -58,7 +59,8 @@ public class BridgeBuilder extends ThingBuilder {
public static BridgeBuilder create(Bridge bridge) {
return BridgeBuilder.create(bridge.getThingTypeUID(), bridge.getUID()).withBridge(bridge.getBridgeUID())
.withChannels(bridge.getChannels()).withConfiguration(bridge.getConfiguration())
.withLabel(bridge.getLabel()).withLocation(bridge.getLocation()).withProperties(bridge.getProperties());
.withLabel(bridge.getLabel()).withLocation(bridge.getLocation()).withProperties(bridge.getProperties())
.withSemanticEquipmentTag(bridge.getSemanticEquipmentTag());
}
@Override
@ -121,4 +123,9 @@ public class BridgeBuilder extends ThingBuilder {
public BridgeBuilder withLocation(@Nullable String location) {
return (BridgeBuilder) super.withLocation(location);
}
@Override
public BridgeBuilder withSemanticEquipmentTag(@Nullable String semanticEquipmentTag) {
return (BridgeBuilder) super.withSemanticEquipmentTag(semanticEquipmentTag);
}
}

View File

@ -36,6 +36,7 @@ import org.openhab.core.thing.util.ThingHelper;
*
* @author Dennis Nobel - Initial contribution
* @author Kai Kreuzer - Refactoring to make BridgeBuilder a subclass
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class ThingBuilder {
@ -48,6 +49,7 @@ public class ThingBuilder {
private @Nullable ThingUID bridgeUID;
private @Nullable Map<String, String> properties;
private @Nullable String location;
private @Nullable String semanticEquipmentTag;
protected ThingBuilder(ThingTypeUID thingTypeUID, ThingUID thingUID) {
this.thingUID = thingUID;
@ -86,7 +88,8 @@ public class ThingBuilder {
public static ThingBuilder create(Thing thing) {
return ThingBuilder.create(thing.getThingTypeUID(), thing.getUID()).withBridge(thing.getBridgeUID())
.withChannels(thing.getChannels()).withConfiguration(thing.getConfiguration())
.withLabel(thing.getLabel()).withLocation(thing.getLocation()).withProperties(thing.getProperties());
.withLabel(thing.getLabel()).withLocation(thing.getLocation()).withProperties(thing.getProperties())
.withSemanticEquipmentTag(thing.getSemanticEquipmentTag());
}
/**
@ -251,6 +254,17 @@ public class ThingBuilder {
return this;
}
/**
* Set the semantic (equipment) tag for this thing
*
* @param semanticEquipmentTag a string with semantic (equipment) tag for this thing
* @return the {@link ThingBuilder} itself
*/
public ThingBuilder withSemanticEquipmentTag(@Nullable String semanticEquipmentTag) {
this.semanticEquipmentTag = semanticEquipmentTag;
return this;
}
protected Thing populate(ThingImpl thing) {
thing.setLabel(label);
thing.setChannels(channels);
@ -262,6 +276,7 @@ public class ThingBuilder {
}
}
thing.setLocation(location);
thing.setSemanticEquipmentTag(semanticEquipmentTag);
return thing;
}

View File

@ -22,6 +22,7 @@ import java.util.Map;
* @author Stefan Bußweiler - Added new thing status handling
* @author Simon Kaufmann - Added label
* @author Wouter Born - Let (Enriched)ThingDTO extend AbstractThingDTO so both can define their own "channels" type
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
public abstract class AbstractThingDTO {
@ -32,12 +33,14 @@ public abstract class AbstractThingDTO {
public String UID;
public String thingTypeUID;
public String location;
public String semanticEquipmentTag;
protected AbstractThingDTO() {
}
protected AbstractThingDTO(String thingTypeUID, String uid, String label, String bridgeUID,
Map<String, Object> configuration, Map<String, String> properties, String location) {
Map<String, Object> configuration, Map<String, String> properties, String location,
String semanticEquipmentTag) {
this.thingTypeUID = thingTypeUID;
this.UID = uid;
this.label = label;
@ -45,5 +48,6 @@ public abstract class AbstractThingDTO {
this.configuration = configuration;
this.properties = properties;
this.location = location;
this.semanticEquipmentTag = semanticEquipmentTag;
}
}

View File

@ -19,6 +19,7 @@ import java.util.List;
* Stripped thing types exclude the parameters, configDescription and channels
*
* @author Miki Jankov - Initial contribution
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
public class StrippedThingTypeDTO {
@ -29,12 +30,13 @@ public class StrippedThingTypeDTO {
public boolean listed;
public List<String> supportedBridgeTypeUIDs;
public boolean bridge;
public String semanticEquipmentTag;
public StrippedThingTypeDTO() {
}
public StrippedThingTypeDTO(String uid, String label, String description, String category, boolean listed,
List<String> supportedBridgeTypeUIDs, boolean bridge) {
List<String> supportedBridgeTypeUIDs, boolean bridge, String semanticEquipmentTag) {
this.UID = uid;
this.label = label;
this.description = description;
@ -42,5 +44,6 @@ public class StrippedThingTypeDTO {
this.listed = listed;
this.supportedBridgeTypeUIDs = supportedBridgeTypeUIDs;
this.bridge = bridge;
this.semanticEquipmentTag = semanticEquipmentTag;
}
}

View File

@ -23,6 +23,7 @@ import org.openhab.core.thing.type.ThingType;
* objects (DTOs).
*
* @author Miki Jankov - Initial contribution
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class StrippedThingTypeDTOMapper {
@ -36,6 +37,6 @@ public class StrippedThingTypeDTOMapper {
public static StrippedThingTypeDTO map(ThingType thingType, Locale locale) {
return new StrippedThingTypeDTO(thingType.getUID().toString(), thingType.getLabel(), thingType.getDescription(),
thingType.getCategory(), thingType.isListed(), thingType.getSupportedBridgeTypeUIDs(),
thingType instanceof BridgeType);
thingType instanceof BridgeType, thingType.getSemanticEquipmentTag());
}
}

View File

@ -23,6 +23,7 @@ import java.util.Map;
* @author Stefan Bußweiler - Added new thing status handling
* @author Simon Kaufmann - Added label
* @author Wouter Born - Let (Enriched)ThingDTO extend AbstractThingDTO so both can define their own "channels" type
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
public class ThingDTO extends AbstractThingDTO {
@ -32,8 +33,9 @@ public class ThingDTO extends AbstractThingDTO {
}
protected ThingDTO(String thingTypeUID, String uid, String label, String bridgeUID, List<ChannelDTO> channels,
Map<String, Object> configuration, Map<String, String> properties, String location) {
super(thingTypeUID, uid, label, bridgeUID, configuration, properties, location);
Map<String, Object> configuration, Map<String, String> properties, String location,
String semanticEquipmentTag) {
super(thingTypeUID, uid, label, bridgeUID, configuration, properties, location, semanticEquipmentTag);
this.channels = channels;
}
}

View File

@ -32,6 +32,7 @@ import org.openhab.core.thing.util.ThingHelper;
*
* @author Stefan Bußweiler - Initial contribution
* @author Kai Kreuzer - Added DTO to Thing mapping
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class ThingDTOMapper {
@ -54,7 +55,8 @@ public class ThingDTOMapper {
final ThingUID bridgeUID = thing.getBridgeUID();
return new ThingDTO(thingTypeUID, thingUID, thing.getLabel(), bridgeUID != null ? bridgeUID.toString() : null,
channelDTOs, toMap(thing.getConfiguration()), thing.getProperties(), thing.getLocation());
channelDTOs, toMap(thing.getConfiguration()), thing.getProperties(), thing.getLocation(),
thing.getSemanticEquipmentTag());
}
/**

View File

@ -25,6 +25,7 @@ import org.openhab.core.config.core.dto.ConfigDescriptionParameterGroupDTO;
* @author Thomas Höfer - Added thing and thing type properties
* @author Chris Jackson - Added parameter groups
* @author Miki Jankov - Introducing StrippedThingTypeDTO
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
public class ThingTypeDTO extends StrippedThingTypeDTO {
@ -42,7 +43,7 @@ public class ThingTypeDTO extends StrippedThingTypeDTO {
List<ConfigDescriptionParameterDTO> configParameters, List<ChannelDefinitionDTO> channels,
List<ChannelGroupDefinitionDTO> channelGroups, List<String> supportedBridgeTypeUIDs,
Map<String, String> properties, boolean bridge, List<ConfigDescriptionParameterGroupDTO> parameterGroups,
List<String> extensibleChannelTypeIds) {
List<String> extensibleChannelTypeIds, String semanticEquipmentTag) {
this.UID = uid;
this.label = label;
this.description = description;
@ -56,5 +57,6 @@ public class ThingTypeDTO extends StrippedThingTypeDTO {
this.bridge = bridge;
this.parameterGroups = parameterGroups;
this.extensibleChannelTypeIds = extensibleChannelTypeIds;
this.semanticEquipmentTag = semanticEquipmentTag;
}
}

View File

@ -44,6 +44,7 @@ import org.openhab.core.thing.binding.builder.ThingStatusInfoBuilder;
* @author Thomas Höfer - Added thing and thing type properties
* @author Simon Kaufmann - Added label
* @author Christoph Weitkamp - Added method {@code getChannel(ChannelUID)}
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class ThingImpl implements Thing {
@ -64,6 +65,8 @@ public class ThingImpl implements Thing {
private @Nullable String location;
private @Nullable String semanticEquipmentTag;
private transient volatile ThingStatusInfo status = ThingStatusInfoBuilder
.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.NONE).build();
@ -258,6 +261,8 @@ public class ThingImpl implements Thing {
sb.append(getStatus());
sb.append(", StatusInfo=");
sb.append(getStatusInfo());
sb.append(", SemanticEquipmentTag=");
sb.append(getSemanticEquipmentTag());
sb.append(")");
return sb.toString();
}
@ -284,4 +289,14 @@ public class ThingImpl implements Thing {
ThingImpl other = (ThingImpl) obj;
return uid.equals(other.uid);
}
@Override
public @Nullable String getSemanticEquipmentTag() {
return semanticEquipmentTag;
}
@Override
public void setSemanticEquipmentTag(@Nullable String semanticEquipmentTag) {
this.semanticEquipmentTag = semanticEquipmentTag;
}
}

View File

@ -18,6 +18,7 @@ import org.openhab.core.thing.dto.ThingDTO;
* The {@link ThingStorageEntity} is an entity for Thing storage
*
* @author Jan N. Klug - Initial contribution
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
public class ThingStorageEntity extends ThingDTO {
public boolean isBridge = false;
@ -28,7 +29,7 @@ public class ThingStorageEntity extends ThingDTO {
public ThingStorageEntity(ThingDTO thingDTO, boolean isBridge) {
super(thingDTO.thingTypeUID, thingDTO.UID, thingDTO.label, thingDTO.bridgeUID, thingDTO.channels,
thingDTO.configuration, thingDTO.properties, thingDTO.location);
thingDTO.configuration, thingDTO.properties, thingDTO.location, thingDTO.semanticEquipmentTag);
this.isBridge = isBridge;
}
}

View File

@ -32,6 +32,7 @@ import org.openhab.core.thing.ThingTypeUID;
* @author Michael Grammling - Initial contribution
* @author Thomas Höfer - Added thing and thing type properties
* @author Andre Fuechsel - Added representationProperty
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class BridgeType extends ThingType {
@ -58,16 +59,17 @@ public class BridgeType extends ThingType {
* @param properties the properties this Thing type provides (could be null)
* @param configDescriptionURI the link to the concrete ConfigDescription (could be null)
* @param extensibleChannelTypeIds the channel-type ids this thing-type is extensible with (could be null or empty).
* @param semanticEquipmentTag the semantic (equipment) tag of the bridge (could be null)
* @throws IllegalArgumentException if the UID is null or empty, or the meta information is null
*/
BridgeType(ThingTypeUID uid, @Nullable List<String> supportedBridgeTypeUIDs, String label,
@Nullable String description, @Nullable String category, boolean listed,
@Nullable String representationProperty, @Nullable List<ChannelDefinition> channelDefinitions,
@Nullable List<ChannelGroupDefinition> channelGroupDefinitions, @Nullable Map<String, String> properties,
@Nullable URI configDescriptionURI, @Nullable List<String> extensibleChannelTypeIds)
throws IllegalArgumentException {
@Nullable URI configDescriptionURI, @Nullable List<String> extensibleChannelTypeIds,
@Nullable String semanticEquipmentTag) throws IllegalArgumentException {
super(uid, supportedBridgeTypeUIDs, label, description, category, listed, representationProperty,
channelDefinitions, channelGroupDefinitions, properties, configDescriptionURI,
extensibleChannelTypeIds);
channelDefinitions, channelGroupDefinitions, properties, configDescriptionURI, extensibleChannelTypeIds,
semanticEquipmentTag);
}
}

View File

@ -35,6 +35,7 @@ import org.openhab.core.thing.ThingTypeUID;
* @author Simon Kaufmann - Added listed field
* @author Andre Fuechsel - Added representationProperty field
* @author Stefan Triller - Added category field
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class ThingType extends AbstractDescriptionType {
@ -47,6 +48,7 @@ public class ThingType extends AbstractDescriptionType {
private final @Nullable String representationProperty;
private final boolean listed;
private final @Nullable String category;
private final @Nullable String semanticEquipmentTag;
/**
* Creates a new instance of this class with the specified parameters.
@ -59,6 +61,7 @@ public class ThingType extends AbstractDescriptionType {
* (must neither be null nor empty)
* @param description the human-readable description for the according type
* (could be null or empty)
* @param category the category of the thing (could be null)
* @param listed determines whether it should be listed for manually pairing or not
* @param representationProperty name of the property that uniquely identifies this Thing
* @param channelDefinitions the channels this Thing type provides (could be null or empty)
@ -67,14 +70,15 @@ public class ThingType extends AbstractDescriptionType {
* @param properties the properties this Thing type provides (could be null)
* @param configDescriptionURI the link to the concrete ConfigDescription (could be null)
* @param extensibleChannelTypeIds the channel-type ids this thing-type is extensible with (could be null or empty).
* @param semanticEquipmentTag the semantic (equipment) tag of the thing (could be null)
* @throws IllegalArgumentException if the UID is null or empty, or the meta information is null
*/
ThingType(ThingTypeUID uid, @Nullable List<String> supportedBridgeTypeUIDs, String label,
@Nullable String description, @Nullable String category, boolean listed,
@Nullable String representationProperty, @Nullable List<ChannelDefinition> channelDefinitions,
@Nullable List<ChannelGroupDefinition> channelGroupDefinitions, @Nullable Map<String, String> properties,
@Nullable URI configDescriptionURI, @Nullable List<String> extensibleChannelTypeIds)
throws IllegalArgumentException {
@Nullable URI configDescriptionURI, @Nullable List<String> extensibleChannelTypeIds,
@Nullable String semanticEquipmentTag) throws IllegalArgumentException {
super(uid, label, description, configDescriptionURI);
this.category = category;
@ -89,6 +93,7 @@ public class ThingType extends AbstractDescriptionType {
this.extensibleChannelTypeIds = extensibleChannelTypeIds == null ? List.of()
: Collections.unmodifiableList(extensibleChannelTypeIds);
this.properties = properties == null ? Map.of() : Collections.unmodifiableMap(properties);
this.semanticEquipmentTag = semanticEquipmentTag;
}
/**
@ -206,4 +211,13 @@ public class ThingType extends AbstractDescriptionType {
public List<String> getExtensibleChannelTypeIds() {
return extensibleChannelTypeIds;
}
/**
* Get the semantic (equipment) tag of this thing type. May be {code null}.
*
* @return the semantic (equipment) tag or {@code null} if no tag has been configured.
*/
public @Nullable String getSemanticEquipmentTag() {
return semanticEquipmentTag;
}
}

View File

@ -24,6 +24,7 @@ import org.openhab.core.thing.ThingTypeUID;
* A {@link ThingType} builder.
*
* @author Henning Treu - Initial contribution
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class ThingTypeBuilder {
@ -42,6 +43,7 @@ public class ThingTypeBuilder {
private final String bindingId;
private final String thingTypeId;
private String label;
private @Nullable String semanticEquipmentTag;
/**
* Create and return a {@link ThingTypeBuilder} with the given {@code bindingId}, {@code thingTypeId} and
@ -99,6 +101,7 @@ public class ThingTypeBuilder {
configDescriptionURI = thingType.getConfigDescriptionURI();
listed = thingType.isListed();
category = thingType.getCategory();
semanticEquipmentTag = thingType.getSemanticEquipmentTag();
}
/**
@ -120,7 +123,7 @@ public class ThingTypeBuilder {
return new ThingType(new ThingTypeUID(bindingId, thingTypeId), supportedBridgeTypeUIDs, label, description,
category, listed, representationProperty, channelDefinitions, channelGroupDefinitions, properties,
configDescriptionURI, extensibleChannelTypeIds);
configDescriptionURI, extensibleChannelTypeIds, semanticEquipmentTag);
}
/**
@ -142,7 +145,7 @@ public class ThingTypeBuilder {
return new BridgeType(new ThingTypeUID(bindingId, thingTypeId), supportedBridgeTypeUIDs, label, description,
category, listed, representationProperty, channelDefinitions, channelGroupDefinitions, properties,
configDescriptionURI, extensibleChannelTypeIds);
configDescriptionURI, extensibleChannelTypeIds, semanticEquipmentTag);
}
public ThingTypeBuilder withLabel(String label) {
@ -199,4 +202,9 @@ public class ThingTypeBuilder {
this.supportedBridgeTypeUIDs = supportedBridgeTypeUIDs;
return this;
}
public ThingTypeBuilder withSemanticEquipmentTag(String semanticEquipmentTag) {
this.semanticEquipmentTag = semanticEquipmentTag;
return this;
}
}

View File

@ -45,6 +45,7 @@ import org.openhab.core.thing.internal.ThingImpl;
* ThingTypeDescription
* @author Dennis Nobel - Removed createAndBindItems method
* @author Kai Kreuzer - Added merge method
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class ThingHelper {
@ -76,6 +77,10 @@ public class ThingHelper {
if (!Objects.equals(a.getLocation(), b.getLocation())) {
return false;
}
// semantic equipment tag
if (!Objects.equals(a.getSemanticEquipmentTag(), b.getSemanticEquipmentTag())) {
return false;
}
// channels
Set<Channel> channelsOfA = new HashSet<>(a.getChannels());
Set<Channel> channelsOfB = new HashSet<>(b.getChannels());
@ -202,10 +207,11 @@ public class ThingHelper {
builder.withChannels(thing.getChannels());
}
if (updatedContents.location != null) {
builder.withLocation(updatedContents.location);
// Update the semantic equipment tag
if (updatedContents.semanticEquipmentTag != null) {
builder.withSemanticEquipmentTag(updatedContents.semanticEquipmentTag);
} else {
builder.withLocation(thing.getLocation());
builder.withSemanticEquipmentTag(thing.getSemanticEquipmentTag());
}
Thing mergedThing = builder.build();

View File

@ -35,6 +35,7 @@ import com.thoughtworks.xstream.io.HierarchicalStreamReader;
* @author Michael Grammling - Initial contribution
* @author Thomas Höfer - Added thing and thing type properties
* @author Andre Fuechsel - Added representationProperty
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class BridgeTypeConverter extends ThingTypeConverter {
@ -49,8 +50,8 @@ public class BridgeTypeConverter extends ThingTypeConverter {
return new BridgeTypeXmlResult(new ThingTypeUID(getUID(attributes, context)),
readSupportedBridgeTypeUIDs(nodeIterator, context), readLabel(nodeIterator),
readDescription(nodeIterator), readCategory(nodeIterator), getListed(attributes),
getExtensibleChannelTypeIds(attributes), getChannelTypeReferenceObjects(nodeIterator),
getProperties(nodeIterator), getRepresentationProperty(nodeIterator),
getConfigDescriptionObjects(nodeIterator));
getExtensibleChannelTypeIds(attributes), getSemanticEquipmentTag(nodeIterator),
getChannelTypeReferenceObjects(nodeIterator), getProperties(nodeIterator),
getRepresentationProperty(nodeIterator), getConfigDescriptionObjects(nodeIterator));
}
}

View File

@ -33,17 +33,19 @@ import com.thoughtworks.xstream.converters.ConversionException;
* @author Michael Grammling - Initial contribution
* @author Thomas Höfer - Added thing and thing type properties
* @author Andre Fuechsel - Added representationProperty
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class BridgeTypeXmlResult extends ThingTypeXmlResult {
public BridgeTypeXmlResult(ThingTypeUID bridgeTypeUID, @Nullable List<String> supportedBridgeTypeUIDs, String label,
@Nullable String description, @Nullable String category, boolean listed,
@Nullable List<String> extensibleChannelTypeIds,
@Nullable List<String> extensibleChannelTypeIds, @Nullable String semanticEquipmentTag,
@Nullable List<ChannelXmlResult>[] channelTypeReferenceObjects, @Nullable List<NodeValue> properties,
@Nullable String representationProperty, Object[] configDescriptionObjects) {
super(bridgeTypeUID, supportedBridgeTypeUIDs, label, description, category, listed, extensibleChannelTypeIds,
channelTypeReferenceObjects, properties, representationProperty, configDescriptionObjects);
semanticEquipmentTag, channelTypeReferenceObjects, properties, representationProperty,
configDescriptionObjects);
}
@Override
@ -59,6 +61,6 @@ public class BridgeTypeXmlResult extends ThingTypeXmlResult {
+ ", channelTypeReferences=" + channelTypeReferences + ", channelGroupTypeReferences="
+ channelGroupTypeReferences + ", extensibelChannelTypeIds=" + extensibleChannelTypeIds
+ ", properties=" + properties + ", configDescriptionURI=" + configDescriptionURI
+ ", configDescription=" + configDescription + "]";
+ ", configDescription=" + configDescription + ", semanticEquipmentTag=" + semanticEquipmentTag + "]";
}
}

View File

@ -48,6 +48,7 @@ import com.thoughtworks.xstream.XStream;
* @author Thomas Höfer - Added thing and thing type properties
* @author Chris Jackson - Added parameter groups and channel properties
* @author Moritz Kammerer - Added triggers
* @author Andrew Fiddian-Green - Added equipment property
*/
@NonNullByDefault
public class ThingDescriptionReader extends XmlDocumentReader<List<?>> {
@ -120,5 +121,6 @@ public class ThingDescriptionReader extends XmlDocumentReader<List<?>> {
xstream.alias("representation-property", NodeValue.class);
xstream.alias("command-options", NodeList.class);
xstream.alias("autoUpdatePolicy", NodeValue.class);
xstream.alias("semantic-equipment-tag", NodeValue.class);
}
}

View File

@ -41,6 +41,7 @@ import com.thoughtworks.xstream.io.HierarchicalStreamReader;
* @author Thomas Höfer - Added thing and thing type properties
* @author Chris Jackson - Added channel properties
* @author Andre Fuechsel - Added representationProperty
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class ThingTypeConverter extends AbstractDescriptionTypeConverter<ThingTypeXmlResult> {
@ -101,9 +102,9 @@ public class ThingTypeConverter extends AbstractDescriptionTypeConverter<ThingTy
return new ThingTypeXmlResult(new ThingTypeUID(super.getUID(attributes, context)),
readSupportedBridgeTypeUIDs(nodeIterator, context), super.readLabel(nodeIterator),
super.readDescription(nodeIterator), readCategory(nodeIterator), getListed(attributes),
getExtensibleChannelTypeIds(attributes), getChannelTypeReferenceObjects(nodeIterator),
getProperties(nodeIterator), getRepresentationProperty(nodeIterator),
super.getConfigDescriptionObjects(nodeIterator));
getExtensibleChannelTypeIds(attributes), getSemanticEquipmentTag(nodeIterator),
getChannelTypeReferenceObjects(nodeIterator), getProperties(nodeIterator),
getRepresentationProperty(nodeIterator), super.getConfigDescriptionObjects(nodeIterator));
}
protected List<String> getExtensibleChannelTypeIds(Map<String, String> attributes) {
@ -135,4 +136,8 @@ public class ThingTypeConverter extends AbstractDescriptionTypeConverter<ThingTy
protected @Nullable String getRepresentationProperty(NodeIterator nodeIterator) {
return (String) nodeIterator.nextValue("representation-property", false);
}
protected @Nullable String getSemanticEquipmentTag(NodeIterator nodeIterator) {
return (String) nodeIterator.nextValue("semantic-equipment-tag", false);
}
}

View File

@ -45,6 +45,7 @@ import com.thoughtworks.xstream.converters.ConversionException;
* @author Simon Kaufmann - Added listed field
* @author Andre Fuechsel - Added representationProperty field
* @author Stefan Triller - Added category field
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class ThingTypeXmlResult {
@ -62,10 +63,11 @@ public class ThingTypeXmlResult {
protected @Nullable List<NodeValue> properties;
protected URI configDescriptionURI;
protected ConfigDescription configDescription;
protected @Nullable String semanticEquipmentTag;
public ThingTypeXmlResult(ThingTypeUID thingTypeUID, @Nullable List<String> supportedBridgeTypeUIDs, String label,
@Nullable String description, @Nullable String category, boolean listed,
@Nullable List<String> extensibleChannelTypeIds,
@Nullable List<String> extensibleChannelTypeIds, @Nullable String semanticEquipmentTag,
@Nullable List<ChannelXmlResult>[] channelTypeReferenceObjects, @Nullable List<NodeValue> properties,
@Nullable String representationProperty, Object[] configDescriptionObjects) {
this.thingTypeUID = thingTypeUID;
@ -81,6 +83,7 @@ public class ThingTypeXmlResult {
this.properties = properties;
this.configDescriptionURI = (URI) configDescriptionObjects[0];
this.configDescription = (ConfigDescription) configDescriptionObjects[1];
this.semanticEquipmentTag = semanticEquipmentTag;
}
public ThingTypeUID getUID() {
@ -197,6 +200,11 @@ public class ThingTypeXmlResult {
builder.withExtensibleChannelTypeIds(extensibleChannelTypeIds);
}
String semanticEquipmentTag = this.semanticEquipmentTag;
if (semanticEquipmentTag != null) {
builder.withSemanticEquipmentTag(semanticEquipmentTag);
}
return builder;
}
@ -212,6 +220,6 @@ public class ThingTypeXmlResult {
+ ", channelTypeReferences=" + channelTypeReferences + ", channelGroupTypeReferences="
+ channelGroupTypeReferences + ", extensibelChannelTypeIds=" + extensibleChannelTypeIds
+ ", properties=" + properties + ", configDescriptionURI=" + configDescriptionURI
+ ", configDescription=" + configDescription + "]";
+ ", configDescription=" + configDescription + ", semanticEquipmentTag=" + semanticEquipmentTag + "]";
}
}

View File

@ -39,6 +39,7 @@ import org.openhab.core.thing.internal.ThingImpl;
* This is the test class for {@link ThingDTO}.
*
* @author Christoph Weitkamp - Initial contribution
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class ThingDTOTest {
@ -55,7 +56,7 @@ public class ThingDTOTest {
ChannelBuilder.create(new ChannelUID(THING_UID, "channel1"), CoreItemFactory.STRING).build(),
ChannelBuilder.create(new ChannelUID(THING_UID, "channel2"), CoreItemFactory.STRING).build())
.withConfiguration(new Configuration(Map.of("param1", "value1"))).withProperties(properties)
.withLocation("Somewhere over the rainbow").build();
.withLocation("Somewhere over the rainbow").withSemanticEquipmentTag("MotionDetector").build();
Thing result = ThingDTOMapper.map(ThingDTOMapper.map(subject), false);
assertThat(result, is(instanceOf(ThingImpl.class)));
assertThat(result.getThingTypeUID(), is(THING_TYPE_UID));
@ -67,6 +68,7 @@ public class ThingDTOTest {
assertThat(result.getProperties().values(), hasSize(1));
assertThat(result.getProperties(), is(subject.getProperties()));
assertThat(result.getLocation(), is(subject.getLocation()));
assertThat(result.getSemanticEquipmentTag(), is(subject.getSemanticEquipmentTag()));
}
@Test

View File

@ -62,6 +62,7 @@ public class ThingDescriptionReaderTest {
assertThat(thingTypeXmlResult.getUID().toString(), is("hue:lamp"));
assertThat(thingTypeXmlResult.label, is("HUE Lamp"));
assertThat(thingTypeXmlResult.description, is("My own great HUE Lamp."));
assertThat(thingTypeXmlResult.semanticEquipmentTag, is("LightBulb"));
assertThat(channelGroupTypeXmlResults.size(), is(1));

View File

@ -12,6 +12,8 @@
<label>HUE Lamp</label>
<description>My own great HUE Lamp.</description>
<semantic-equipment-tag>LightBulb</semantic-equipment-tag>
<channel-groups>
<channel-group id="alarm_system" typeId="alarm_system"/>
</channel-groups>

View File

@ -68,10 +68,13 @@ import org.openhab.core.thing.type.ThingTypeBuilder;
* @author Alex Tugarev - Adapted for constructor modification of ConfigDescriptionParameter
* @author Thomas Höfer - Thing type constructor modified because of thing properties introduction
* @author Wouter Born - Migrate tests from Groovy to Java
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/
@NonNullByDefault
public class ThingFactoryTest extends JavaOSGiTest {
private static final String SEMANTIC_EQUIPMENT_TAG = "MotionDetector";
@Test
public void createSimpleThing() {
ThingType thingType = ThingTypeBuilder.instance("bindingId", "thingTypeId", "label").build();
@ -349,4 +352,13 @@ public class ThingFactoryTest extends JavaOSGiTest {
});
registerService(channelGroupTypeProvider);
}
@Test
public void createThingWithTag() {
ThingType thingType = ThingTypeBuilder.instance(new ThingTypeUID("bindingId:thingType"), "label")
.withSemanticEquipmentTag(SEMANTIC_EQUIPMENT_TAG).build();
Thing thing = ThingFactory.createThing(thingType, new ThingUID(thingType.getUID(), "thingId"),
new Configuration());
assertThat(thing.getSemanticEquipmentTag(), is(SEMANTIC_EQUIPMENT_TAG));
}
}