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 Dimitar Ivanov - replaced Firmware UID with thing UID and firmware version
* @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification * @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations * @author Wouter Born - Migrated to OpenAPI annotations
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@Component @Component
@JaxrsResource @JaxrsResource
@ -326,14 +327,15 @@ public class ThingResource implements RESTResource {
lastModified = Date.from(Instant.now().truncatedTo(ChronoUnit.SECONDS)); 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) return Response.ok(new Stream2JSONInputStream(thingStream)).lastModified(lastModified)
.cacheControl(RESTConstants.CACHE_CONTROL).build(); .cacheControl(RESTConstants.CACHE_CONTROL).build();
} }
if (summary != null && summary) { if (summary != null && summary) {
thingStream = dtoMapper.limitToFields(thingStream, 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(); 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 Yannick Schaus - Added filter to getAll
* @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification * @author Markus Rathgeb - Migrated to JAX-RS Whiteboard Specification
* @author Wouter Born - Migrated to OpenAPI annotations * @author Wouter Born - Migrated to OpenAPI annotations
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@Component @Component
@JaxrsResource @JaxrsResource
@ -188,7 +189,7 @@ public class ThingTypeResource implements RESTResource {
thingType.getCategory(), thingType.isListed(), parameters, channelDefinitions, thingType.getCategory(), thingType.isListed(), parameters, channelDefinitions,
convertToChannelGroupDefinitionDTOs(thingType.getChannelGroupDefinitions(), locale), convertToChannelGroupDefinitionDTOs(thingType.getChannelGroupDefinitions(), locale),
thingType.getSupportedBridgeTypeUIDs(), thingType.getProperties(), thingType instanceof BridgeType, thingType.getSupportedBridgeTypeUIDs(), thingType.getProperties(), thingType instanceof BridgeType,
parameterGroups, thingType.getExtensibleChannelTypeIds()); parameterGroups, thingType.getExtensibleChannelTypeIds(), thingType.getSemanticEquipmentTag());
} }
private List<ChannelGroupDefinitionDTO> convertToChannelGroupDefinitionDTOs( 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 Kai Kreuzer - Removed links and items
* @author Chris Jackson - Added 'editable' flag * @author Chris Jackson - Added 'editable' flag
* @author Wouter Born - Let (Enriched)ThingDTO extend AbstractThingDTO so both can define their own "channels" type * @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 { public class EnrichedThingDTO extends AbstractThingDTO {
@ -46,7 +47,7 @@ public class EnrichedThingDTO extends AbstractThingDTO {
EnrichedThingDTO(ThingDTO thingDTO, List<EnrichedChannelDTO> channels, ThingStatusInfo statusInfo, EnrichedThingDTO(ThingDTO thingDTO, List<EnrichedChannelDTO> channels, ThingStatusInfo statusInfo,
FirmwareStatusDTO firmwareStatus, boolean editable) { FirmwareStatusDTO firmwareStatus, boolean editable) {
super(thingDTO.thingTypeUID, thingDTO.UID, thingDTO.label, thingDTO.bridgeUID, thingDTO.configuration, 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.channels = channels;
this.statusInfo = statusInfo; this.statusInfo = statusInfo;
this.firmwareStatus = firmwareStatus; this.firmwareStatus = firmwareStatus;

View File

@ -23,6 +23,9 @@
<jaxb:bindings node="//xs:simpleType[@name='semanticPropertyOrPointTag']"> <jaxb:bindings node="//xs:simpleType[@name='semanticPropertyOrPointTag']">
<jaxb:typesafeEnumClass map="false"/> <jaxb:typesafeEnumClass map="false"/>
</jaxb:bindings> </jaxb:bindings>
<jaxb:bindings node="//xs:simpleType[@name='semanticEquipmentTag']">
<jaxb:typesafeEnumClass map="false"/>
</jaxb:bindings>
</jaxb:bindings> </jaxb:bindings>
<jaxb:bindings schemaLocation="../update/update-description-1.0.0.xsd"> <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="label" type="xs:string"/>
<xs:element name="description" type="xs:string" minOccurs="0"/> <xs:element name="description" type="xs:string" minOccurs="0"/>
<xs:element name="category" 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:choice minOccurs="0">
<xs:element name="channels" type="thing-description:channels"/> <xs:element name="channels" type="thing-description:channels"/>
<xs:element name="channel-groups" type="thing-description:channelGroups"/> <xs:element name="channel-groups" type="thing-description:channelGroups"/>
@ -293,7 +294,7 @@
<xs:enumeration value="Current"/> <xs:enumeration value="Current"/>
<xs:enumeration value="Frequency"/> <xs:enumeration value="Frequency"/>
<xs:enumeration value="Gas"/> <xs:enumeration value="Gas"/>
<xs:enumeration value="Application"/> <xs:enumeration value="App"/>
<xs:enumeration value="Channel"/> <xs:enumeration value="Channel"/>
<xs:enumeration value="Mode"/> <xs:enumeration value="Mode"/>
<xs:enumeration value="SoundVolume"/> <xs:enumeration value="SoundVolume"/>
@ -321,4 +322,64 @@
<!-- End Allowed Semantic Point Tag Values --> <!-- End Allowed Semantic Point Tag Values -->
</xs:restriction> </xs:restriction>
</xs:simpleType> </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> </xs:schema>

View File

@ -35,6 +35,7 @@ import org.openhab.core.thing.binding.ThingHandler;
* @author Kai Kreuzer - Removed linked items from Thing * @author Kai Kreuzer - Removed linked items from Thing
* @author Yordan Zhelev - Added method for getting the enabled status * @author Yordan Zhelev - Added method for getting the enabled status
* @author Christoph Weitkamp - Added method {@code getChannel(ChannelUID)} * @author Christoph Weitkamp - Added method {@code getChannel(ChannelUID)}
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public interface Thing extends Identifiable<ThingUID> { 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. * @return Returns {@code true} if the thing is enabled. Return {@code false} otherwise.
*/ */
boolean isEnabled(); 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 * persist those for future thing initializations
* *
* @author Jan N. Klug - Initial contribution * @author Jan N. Klug - Initial contribution
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public abstract class AbstractStorageBasedTypeProvider public abstract class AbstractStorageBasedTypeProvider
@ -395,6 +396,7 @@ public abstract class AbstractStorageBasedTypeProvider
public Map<String, String> properties = Map.of(); public Map<String, String> properties = Map.of();
public boolean isListed = false; public boolean isListed = false;
public boolean isBridge = false; public boolean isBridge = false;
public @Nullable String semanticEquipmentTag;
} }
static class ChannelDefinitionEntity { static class ChannelDefinitionEntity {

View File

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

View File

@ -62,6 +62,7 @@ import org.slf4j.LoggerFactory;
* @author Kai Kreuzer - Refactored isLinked method to not use deprecated functions anymore * @author Kai Kreuzer - Refactored isLinked method to not use deprecated functions anymore
* @author Christoph Weitkamp - Moved OSGI ServiceTracker from BaseThingHandler to ThingHandlerCallback * @author Christoph Weitkamp - Moved OSGI ServiceTracker from BaseThingHandler to ThingHandlerCallback
* @author Jan N. Klug - added time series support * @author Jan N. Klug - added time series support
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public abstract class BaseThingHandler implements ThingHandler { 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()) return ThingBuilder.create(this.thing.getThingTypeUID(), this.thing.getUID())
.withBridge(this.thing.getBridgeUID()).withChannels(this.thing.getChannels()) .withBridge(this.thing.getBridgeUID()).withChannels(this.thing.getChannels())
.withConfiguration(this.thing.getConfiguration()).withLabel(this.thing.getLabel()) .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 * values
* @author Thomas Höfer - added thing and thing type properties * @author Thomas Höfer - added thing and thing type properties
* @author Chris Jackson - Added properties, label, description * @author Chris Jackson - Added properties, label, description
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class ThingFactory { public class ThingFactory {
@ -91,7 +92,8 @@ public class ThingFactory {
List<Channel> channels = ThingFactoryHelper.createChannels(thingType, thingUID, configDescriptionRegistry); List<Channel> channels = ThingFactoryHelper.createChannels(thingType, thingUID, configDescriptionRegistry);
return createThingBuilder(thingType, thingUID).withConfiguration(configuration).withChannels(channels) 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, 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 Dennis Nobel - Initial contribution
* @author Kai Kreuzer - Refactoring to make BridgeBuilder a subclass of ThingBuilder * @author Kai Kreuzer - Refactoring to make BridgeBuilder a subclass of ThingBuilder
* @author Markus Rathgeb - Override methods to return BridgeBuidler instead of ThingBuidler * @author Markus Rathgeb - Override methods to return BridgeBuidler instead of ThingBuidler
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class BridgeBuilder extends ThingBuilder { public class BridgeBuilder extends ThingBuilder {
@ -58,7 +59,8 @@ public class BridgeBuilder extends ThingBuilder {
public static BridgeBuilder create(Bridge bridge) { public static BridgeBuilder create(Bridge bridge) {
return BridgeBuilder.create(bridge.getThingTypeUID(), bridge.getUID()).withBridge(bridge.getBridgeUID()) return BridgeBuilder.create(bridge.getThingTypeUID(), bridge.getUID()).withBridge(bridge.getBridgeUID())
.withChannels(bridge.getChannels()).withConfiguration(bridge.getConfiguration()) .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 @Override
@ -121,4 +123,9 @@ public class BridgeBuilder extends ThingBuilder {
public BridgeBuilder withLocation(@Nullable String location) { public BridgeBuilder withLocation(@Nullable String location) {
return (BridgeBuilder) super.withLocation(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 Dennis Nobel - Initial contribution
* @author Kai Kreuzer - Refactoring to make BridgeBuilder a subclass * @author Kai Kreuzer - Refactoring to make BridgeBuilder a subclass
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class ThingBuilder { public class ThingBuilder {
@ -48,6 +49,7 @@ public class ThingBuilder {
private @Nullable ThingUID bridgeUID; private @Nullable ThingUID bridgeUID;
private @Nullable Map<String, String> properties; private @Nullable Map<String, String> properties;
private @Nullable String location; private @Nullable String location;
private @Nullable String semanticEquipmentTag;
protected ThingBuilder(ThingTypeUID thingTypeUID, ThingUID thingUID) { protected ThingBuilder(ThingTypeUID thingTypeUID, ThingUID thingUID) {
this.thingUID = thingUID; this.thingUID = thingUID;
@ -86,7 +88,8 @@ public class ThingBuilder {
public static ThingBuilder create(Thing thing) { public static ThingBuilder create(Thing thing) {
return ThingBuilder.create(thing.getThingTypeUID(), thing.getUID()).withBridge(thing.getBridgeUID()) return ThingBuilder.create(thing.getThingTypeUID(), thing.getUID()).withBridge(thing.getBridgeUID())
.withChannels(thing.getChannels()).withConfiguration(thing.getConfiguration()) .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; 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) { protected Thing populate(ThingImpl thing) {
thing.setLabel(label); thing.setLabel(label);
thing.setChannels(channels); thing.setChannels(channels);
@ -262,6 +276,7 @@ public class ThingBuilder {
} }
} }
thing.setLocation(location); thing.setLocation(location);
thing.setSemanticEquipmentTag(semanticEquipmentTag);
return thing; return thing;
} }

View File

@ -22,6 +22,7 @@ import java.util.Map;
* @author Stefan Bußweiler - Added new thing status handling * @author Stefan Bußweiler - Added new thing status handling
* @author Simon Kaufmann - Added label * @author Simon Kaufmann - Added label
* @author Wouter Born - Let (Enriched)ThingDTO extend AbstractThingDTO so both can define their own "channels" type * @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 { public abstract class AbstractThingDTO {
@ -32,12 +33,14 @@ public abstract class AbstractThingDTO {
public String UID; public String UID;
public String thingTypeUID; public String thingTypeUID;
public String location; public String location;
public String semanticEquipmentTag;
protected AbstractThingDTO() { protected AbstractThingDTO() {
} }
protected AbstractThingDTO(String thingTypeUID, String uid, String label, String bridgeUID, 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.thingTypeUID = thingTypeUID;
this.UID = uid; this.UID = uid;
this.label = label; this.label = label;
@ -45,5 +48,6 @@ public abstract class AbstractThingDTO {
this.configuration = configuration; this.configuration = configuration;
this.properties = properties; this.properties = properties;
this.location = location; 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 * Stripped thing types exclude the parameters, configDescription and channels
* *
* @author Miki Jankov - Initial contribution * @author Miki Jankov - Initial contribution
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
public class StrippedThingTypeDTO { public class StrippedThingTypeDTO {
@ -29,12 +30,13 @@ public class StrippedThingTypeDTO {
public boolean listed; public boolean listed;
public List<String> supportedBridgeTypeUIDs; public List<String> supportedBridgeTypeUIDs;
public boolean bridge; public boolean bridge;
public String semanticEquipmentTag;
public StrippedThingTypeDTO() { public StrippedThingTypeDTO() {
} }
public StrippedThingTypeDTO(String uid, String label, String description, String category, boolean listed, 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.UID = uid;
this.label = label; this.label = label;
this.description = description; this.description = description;
@ -42,5 +44,6 @@ public class StrippedThingTypeDTO {
this.listed = listed; this.listed = listed;
this.supportedBridgeTypeUIDs = supportedBridgeTypeUIDs; this.supportedBridgeTypeUIDs = supportedBridgeTypeUIDs;
this.bridge = bridge; this.bridge = bridge;
this.semanticEquipmentTag = semanticEquipmentTag;
} }
} }

View File

@ -23,6 +23,7 @@ import org.openhab.core.thing.type.ThingType;
* objects (DTOs). * objects (DTOs).
* *
* @author Miki Jankov - Initial contribution * @author Miki Jankov - Initial contribution
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class StrippedThingTypeDTOMapper { public class StrippedThingTypeDTOMapper {
@ -36,6 +37,6 @@ public class StrippedThingTypeDTOMapper {
public static StrippedThingTypeDTO map(ThingType thingType, Locale locale) { public static StrippedThingTypeDTO map(ThingType thingType, Locale locale) {
return new StrippedThingTypeDTO(thingType.getUID().toString(), thingType.getLabel(), thingType.getDescription(), return new StrippedThingTypeDTO(thingType.getUID().toString(), thingType.getLabel(), thingType.getDescription(),
thingType.getCategory(), thingType.isListed(), thingType.getSupportedBridgeTypeUIDs(), 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 Stefan Bußweiler - Added new thing status handling
* @author Simon Kaufmann - Added label * @author Simon Kaufmann - Added label
* @author Wouter Born - Let (Enriched)ThingDTO extend AbstractThingDTO so both can define their own "channels" type * @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 { 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, protected ThingDTO(String thingTypeUID, String uid, String label, String bridgeUID, List<ChannelDTO> channels,
Map<String, Object> configuration, Map<String, String> properties, String location) { Map<String, Object> configuration, Map<String, String> properties, String location,
super(thingTypeUID, uid, label, bridgeUID, configuration, properties, location); String semanticEquipmentTag) {
super(thingTypeUID, uid, label, bridgeUID, configuration, properties, location, semanticEquipmentTag);
this.channels = channels; this.channels = channels;
} }
} }

View File

@ -32,6 +32,7 @@ import org.openhab.core.thing.util.ThingHelper;
* *
* @author Stefan Bußweiler - Initial contribution * @author Stefan Bußweiler - Initial contribution
* @author Kai Kreuzer - Added DTO to Thing mapping * @author Kai Kreuzer - Added DTO to Thing mapping
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class ThingDTOMapper { public class ThingDTOMapper {
@ -54,7 +55,8 @@ public class ThingDTOMapper {
final ThingUID bridgeUID = thing.getBridgeUID(); final ThingUID bridgeUID = thing.getBridgeUID();
return new ThingDTO(thingTypeUID, thingUID, thing.getLabel(), bridgeUID != null ? bridgeUID.toString() : null, 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 Thomas Höfer - Added thing and thing type properties
* @author Chris Jackson - Added parameter groups * @author Chris Jackson - Added parameter groups
* @author Miki Jankov - Introducing StrippedThingTypeDTO * @author Miki Jankov - Introducing StrippedThingTypeDTO
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
public class ThingTypeDTO extends StrippedThingTypeDTO { public class ThingTypeDTO extends StrippedThingTypeDTO {
@ -42,7 +43,7 @@ public class ThingTypeDTO extends StrippedThingTypeDTO {
List<ConfigDescriptionParameterDTO> configParameters, List<ChannelDefinitionDTO> channels, List<ConfigDescriptionParameterDTO> configParameters, List<ChannelDefinitionDTO> channels,
List<ChannelGroupDefinitionDTO> channelGroups, List<String> supportedBridgeTypeUIDs, List<ChannelGroupDefinitionDTO> channelGroups, List<String> supportedBridgeTypeUIDs,
Map<String, String> properties, boolean bridge, List<ConfigDescriptionParameterGroupDTO> parameterGroups, Map<String, String> properties, boolean bridge, List<ConfigDescriptionParameterGroupDTO> parameterGroups,
List<String> extensibleChannelTypeIds) { List<String> extensibleChannelTypeIds, String semanticEquipmentTag) {
this.UID = uid; this.UID = uid;
this.label = label; this.label = label;
this.description = description; this.description = description;
@ -56,5 +57,6 @@ public class ThingTypeDTO extends StrippedThingTypeDTO {
this.bridge = bridge; this.bridge = bridge;
this.parameterGroups = parameterGroups; this.parameterGroups = parameterGroups;
this.extensibleChannelTypeIds = extensibleChannelTypeIds; 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 Thomas Höfer - Added thing and thing type properties
* @author Simon Kaufmann - Added label * @author Simon Kaufmann - Added label
* @author Christoph Weitkamp - Added method {@code getChannel(ChannelUID)} * @author Christoph Weitkamp - Added method {@code getChannel(ChannelUID)}
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class ThingImpl implements Thing { public class ThingImpl implements Thing {
@ -64,6 +65,8 @@ public class ThingImpl implements Thing {
private @Nullable String location; private @Nullable String location;
private @Nullable String semanticEquipmentTag;
private transient volatile ThingStatusInfo status = ThingStatusInfoBuilder private transient volatile ThingStatusInfo status = ThingStatusInfoBuilder
.create(ThingStatus.UNINITIALIZED, ThingStatusDetail.NONE).build(); .create(ThingStatus.UNINITIALIZED, ThingStatusDetail.NONE).build();
@ -258,6 +261,8 @@ public class ThingImpl implements Thing {
sb.append(getStatus()); sb.append(getStatus());
sb.append(", StatusInfo="); sb.append(", StatusInfo=");
sb.append(getStatusInfo()); sb.append(getStatusInfo());
sb.append(", SemanticEquipmentTag=");
sb.append(getSemanticEquipmentTag());
sb.append(")"); sb.append(")");
return sb.toString(); return sb.toString();
} }
@ -284,4 +289,14 @@ public class ThingImpl implements Thing {
ThingImpl other = (ThingImpl) obj; ThingImpl other = (ThingImpl) obj;
return uid.equals(other.uid); 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 * The {@link ThingStorageEntity} is an entity for Thing storage
* *
* @author Jan N. Klug - Initial contribution * @author Jan N. Klug - Initial contribution
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
public class ThingStorageEntity extends ThingDTO { public class ThingStorageEntity extends ThingDTO {
public boolean isBridge = false; public boolean isBridge = false;
@ -28,7 +29,7 @@ public class ThingStorageEntity extends ThingDTO {
public ThingStorageEntity(ThingDTO thingDTO, boolean isBridge) { public ThingStorageEntity(ThingDTO thingDTO, boolean isBridge) {
super(thingDTO.thingTypeUID, thingDTO.UID, thingDTO.label, thingDTO.bridgeUID, thingDTO.channels, 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; this.isBridge = isBridge;
} }
} }

View File

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

View File

@ -35,6 +35,7 @@ import org.openhab.core.thing.ThingTypeUID;
* @author Simon Kaufmann - Added listed field * @author Simon Kaufmann - Added listed field
* @author Andre Fuechsel - Added representationProperty field * @author Andre Fuechsel - Added representationProperty field
* @author Stefan Triller - Added category field * @author Stefan Triller - Added category field
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class ThingType extends AbstractDescriptionType { public class ThingType extends AbstractDescriptionType {
@ -47,6 +48,7 @@ public class ThingType extends AbstractDescriptionType {
private final @Nullable String representationProperty; private final @Nullable String representationProperty;
private final boolean listed; private final boolean listed;
private final @Nullable String category; private final @Nullable String category;
private final @Nullable String semanticEquipmentTag;
/** /**
* Creates a new instance of this class with the specified parameters. * 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) * (must neither be null nor empty)
* @param description the human-readable description for the according type * @param description the human-readable description for the according type
* (could be null or empty) * (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 listed determines whether it should be listed for manually pairing or not
* @param representationProperty name of the property that uniquely identifies this Thing * @param representationProperty name of the property that uniquely identifies this Thing
* @param channelDefinitions the channels this Thing type provides (could be null or empty) * @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 properties the properties this Thing type provides (could be null)
* @param configDescriptionURI the link to the concrete ConfigDescription (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 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 * @throws IllegalArgumentException if the UID is null or empty, or the meta information is null
*/ */
ThingType(ThingTypeUID uid, @Nullable List<String> supportedBridgeTypeUIDs, String label, ThingType(ThingTypeUID uid, @Nullable List<String> supportedBridgeTypeUIDs, String label,
@Nullable String description, @Nullable String category, boolean listed, @Nullable String description, @Nullable String category, boolean listed,
@Nullable String representationProperty, @Nullable List<ChannelDefinition> channelDefinitions, @Nullable String representationProperty, @Nullable List<ChannelDefinition> channelDefinitions,
@Nullable List<ChannelGroupDefinition> channelGroupDefinitions, @Nullable Map<String, String> properties, @Nullable List<ChannelGroupDefinition> channelGroupDefinitions, @Nullable Map<String, String> properties,
@Nullable URI configDescriptionURI, @Nullable List<String> extensibleChannelTypeIds) @Nullable URI configDescriptionURI, @Nullable List<String> extensibleChannelTypeIds,
throws IllegalArgumentException { @Nullable String semanticEquipmentTag) throws IllegalArgumentException {
super(uid, label, description, configDescriptionURI); super(uid, label, description, configDescriptionURI);
this.category = category; this.category = category;
@ -89,6 +93,7 @@ public class ThingType extends AbstractDescriptionType {
this.extensibleChannelTypeIds = extensibleChannelTypeIds == null ? List.of() this.extensibleChannelTypeIds = extensibleChannelTypeIds == null ? List.of()
: Collections.unmodifiableList(extensibleChannelTypeIds); : Collections.unmodifiableList(extensibleChannelTypeIds);
this.properties = properties == null ? Map.of() : Collections.unmodifiableMap(properties); 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() { public List<String> getExtensibleChannelTypeIds() {
return extensibleChannelTypeIds; 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. * A {@link ThingType} builder.
* *
* @author Henning Treu - Initial contribution * @author Henning Treu - Initial contribution
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class ThingTypeBuilder { public class ThingTypeBuilder {
@ -42,6 +43,7 @@ public class ThingTypeBuilder {
private final String bindingId; private final String bindingId;
private final String thingTypeId; private final String thingTypeId;
private String label; private String label;
private @Nullable String semanticEquipmentTag;
/** /**
* Create and return a {@link ThingTypeBuilder} with the given {@code bindingId}, {@code thingTypeId} and * Create and return a {@link ThingTypeBuilder} with the given {@code bindingId}, {@code thingTypeId} and
@ -99,6 +101,7 @@ public class ThingTypeBuilder {
configDescriptionURI = thingType.getConfigDescriptionURI(); configDescriptionURI = thingType.getConfigDescriptionURI();
listed = thingType.isListed(); listed = thingType.isListed();
category = thingType.getCategory(); category = thingType.getCategory();
semanticEquipmentTag = thingType.getSemanticEquipmentTag();
} }
/** /**
@ -120,7 +123,7 @@ public class ThingTypeBuilder {
return new ThingType(new ThingTypeUID(bindingId, thingTypeId), supportedBridgeTypeUIDs, label, description, return new ThingType(new ThingTypeUID(bindingId, thingTypeId), supportedBridgeTypeUIDs, label, description,
category, listed, representationProperty, channelDefinitions, channelGroupDefinitions, properties, 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, return new BridgeType(new ThingTypeUID(bindingId, thingTypeId), supportedBridgeTypeUIDs, label, description,
category, listed, representationProperty, channelDefinitions, channelGroupDefinitions, properties, category, listed, representationProperty, channelDefinitions, channelGroupDefinitions, properties,
configDescriptionURI, extensibleChannelTypeIds); configDescriptionURI, extensibleChannelTypeIds, semanticEquipmentTag);
} }
public ThingTypeBuilder withLabel(String label) { public ThingTypeBuilder withLabel(String label) {
@ -199,4 +202,9 @@ public class ThingTypeBuilder {
this.supportedBridgeTypeUIDs = supportedBridgeTypeUIDs; this.supportedBridgeTypeUIDs = supportedBridgeTypeUIDs;
return this; 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 * ThingTypeDescription
* @author Dennis Nobel - Removed createAndBindItems method * @author Dennis Nobel - Removed createAndBindItems method
* @author Kai Kreuzer - Added merge method * @author Kai Kreuzer - Added merge method
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class ThingHelper { public class ThingHelper {
@ -76,6 +77,10 @@ public class ThingHelper {
if (!Objects.equals(a.getLocation(), b.getLocation())) { if (!Objects.equals(a.getLocation(), b.getLocation())) {
return false; return false;
} }
// semantic equipment tag
if (!Objects.equals(a.getSemanticEquipmentTag(), b.getSemanticEquipmentTag())) {
return false;
}
// channels // channels
Set<Channel> channelsOfA = new HashSet<>(a.getChannels()); Set<Channel> channelsOfA = new HashSet<>(a.getChannels());
Set<Channel> channelsOfB = new HashSet<>(b.getChannels()); Set<Channel> channelsOfB = new HashSet<>(b.getChannels());
@ -202,10 +207,11 @@ public class ThingHelper {
builder.withChannels(thing.getChannels()); builder.withChannels(thing.getChannels());
} }
if (updatedContents.location != null) { // Update the semantic equipment tag
builder.withLocation(updatedContents.location); if (updatedContents.semanticEquipmentTag != null) {
builder.withSemanticEquipmentTag(updatedContents.semanticEquipmentTag);
} else { } else {
builder.withLocation(thing.getLocation()); builder.withSemanticEquipmentTag(thing.getSemanticEquipmentTag());
} }
Thing mergedThing = builder.build(); Thing mergedThing = builder.build();

View File

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

View File

@ -33,17 +33,19 @@ import com.thoughtworks.xstream.converters.ConversionException;
* @author Michael Grammling - Initial contribution * @author Michael Grammling - Initial contribution
* @author Thomas Höfer - Added thing and thing type properties * @author Thomas Höfer - Added thing and thing type properties
* @author Andre Fuechsel - Added representationProperty * @author Andre Fuechsel - Added representationProperty
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class BridgeTypeXmlResult extends ThingTypeXmlResult { public class BridgeTypeXmlResult extends ThingTypeXmlResult {
public BridgeTypeXmlResult(ThingTypeUID bridgeTypeUID, @Nullable List<String> supportedBridgeTypeUIDs, String label, public BridgeTypeXmlResult(ThingTypeUID bridgeTypeUID, @Nullable List<String> supportedBridgeTypeUIDs, String label,
@Nullable String description, @Nullable String category, boolean listed, @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 List<ChannelXmlResult>[] channelTypeReferenceObjects, @Nullable List<NodeValue> properties,
@Nullable String representationProperty, Object[] configDescriptionObjects) { @Nullable String representationProperty, Object[] configDescriptionObjects) {
super(bridgeTypeUID, supportedBridgeTypeUIDs, label, description, category, listed, extensibleChannelTypeIds, super(bridgeTypeUID, supportedBridgeTypeUIDs, label, description, category, listed, extensibleChannelTypeIds,
channelTypeReferenceObjects, properties, representationProperty, configDescriptionObjects); semanticEquipmentTag, channelTypeReferenceObjects, properties, representationProperty,
configDescriptionObjects);
} }
@Override @Override
@ -59,6 +61,6 @@ public class BridgeTypeXmlResult extends ThingTypeXmlResult {
+ ", channelTypeReferences=" + channelTypeReferences + ", channelGroupTypeReferences=" + ", channelTypeReferences=" + channelTypeReferences + ", channelGroupTypeReferences="
+ channelGroupTypeReferences + ", extensibelChannelTypeIds=" + extensibleChannelTypeIds + channelGroupTypeReferences + ", extensibelChannelTypeIds=" + extensibleChannelTypeIds
+ ", properties=" + properties + ", configDescriptionURI=" + configDescriptionURI + ", 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 Thomas Höfer - Added thing and thing type properties
* @author Chris Jackson - Added parameter groups and channel properties * @author Chris Jackson - Added parameter groups and channel properties
* @author Moritz Kammerer - Added triggers * @author Moritz Kammerer - Added triggers
* @author Andrew Fiddian-Green - Added equipment property
*/ */
@NonNullByDefault @NonNullByDefault
public class ThingDescriptionReader extends XmlDocumentReader<List<?>> { public class ThingDescriptionReader extends XmlDocumentReader<List<?>> {
@ -120,5 +121,6 @@ public class ThingDescriptionReader extends XmlDocumentReader<List<?>> {
xstream.alias("representation-property", NodeValue.class); xstream.alias("representation-property", NodeValue.class);
xstream.alias("command-options", NodeList.class); xstream.alias("command-options", NodeList.class);
xstream.alias("autoUpdatePolicy", NodeValue.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 Thomas Höfer - Added thing and thing type properties
* @author Chris Jackson - Added channel properties * @author Chris Jackson - Added channel properties
* @author Andre Fuechsel - Added representationProperty * @author Andre Fuechsel - Added representationProperty
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class ThingTypeConverter extends AbstractDescriptionTypeConverter<ThingTypeXmlResult> { 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)), return new ThingTypeXmlResult(new ThingTypeUID(super.getUID(attributes, context)),
readSupportedBridgeTypeUIDs(nodeIterator, context), super.readLabel(nodeIterator), readSupportedBridgeTypeUIDs(nodeIterator, context), super.readLabel(nodeIterator),
super.readDescription(nodeIterator), readCategory(nodeIterator), getListed(attributes), super.readDescription(nodeIterator), readCategory(nodeIterator), getListed(attributes),
getExtensibleChannelTypeIds(attributes), getChannelTypeReferenceObjects(nodeIterator), getExtensibleChannelTypeIds(attributes), getSemanticEquipmentTag(nodeIterator),
getProperties(nodeIterator), getRepresentationProperty(nodeIterator), getChannelTypeReferenceObjects(nodeIterator), getProperties(nodeIterator),
super.getConfigDescriptionObjects(nodeIterator)); getRepresentationProperty(nodeIterator), super.getConfigDescriptionObjects(nodeIterator));
} }
protected List<String> getExtensibleChannelTypeIds(Map<String, String> attributes) { protected List<String> getExtensibleChannelTypeIds(Map<String, String> attributes) {
@ -135,4 +136,8 @@ public class ThingTypeConverter extends AbstractDescriptionTypeConverter<ThingTy
protected @Nullable String getRepresentationProperty(NodeIterator nodeIterator) { protected @Nullable String getRepresentationProperty(NodeIterator nodeIterator) {
return (String) nodeIterator.nextValue("representation-property", false); 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 Simon Kaufmann - Added listed field
* @author Andre Fuechsel - Added representationProperty field * @author Andre Fuechsel - Added representationProperty field
* @author Stefan Triller - Added category field * @author Stefan Triller - Added category field
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class ThingTypeXmlResult { public class ThingTypeXmlResult {
@ -62,10 +63,11 @@ public class ThingTypeXmlResult {
protected @Nullable List<NodeValue> properties; protected @Nullable List<NodeValue> properties;
protected URI configDescriptionURI; protected URI configDescriptionURI;
protected ConfigDescription configDescription; protected ConfigDescription configDescription;
protected @Nullable String semanticEquipmentTag;
public ThingTypeXmlResult(ThingTypeUID thingTypeUID, @Nullable List<String> supportedBridgeTypeUIDs, String label, public ThingTypeXmlResult(ThingTypeUID thingTypeUID, @Nullable List<String> supportedBridgeTypeUIDs, String label,
@Nullable String description, @Nullable String category, boolean listed, @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 List<ChannelXmlResult>[] channelTypeReferenceObjects, @Nullable List<NodeValue> properties,
@Nullable String representationProperty, Object[] configDescriptionObjects) { @Nullable String representationProperty, Object[] configDescriptionObjects) {
this.thingTypeUID = thingTypeUID; this.thingTypeUID = thingTypeUID;
@ -81,6 +83,7 @@ public class ThingTypeXmlResult {
this.properties = properties; this.properties = properties;
this.configDescriptionURI = (URI) configDescriptionObjects[0]; this.configDescriptionURI = (URI) configDescriptionObjects[0];
this.configDescription = (ConfigDescription) configDescriptionObjects[1]; this.configDescription = (ConfigDescription) configDescriptionObjects[1];
this.semanticEquipmentTag = semanticEquipmentTag;
} }
public ThingTypeUID getUID() { public ThingTypeUID getUID() {
@ -197,6 +200,11 @@ public class ThingTypeXmlResult {
builder.withExtensibleChannelTypeIds(extensibleChannelTypeIds); builder.withExtensibleChannelTypeIds(extensibleChannelTypeIds);
} }
String semanticEquipmentTag = this.semanticEquipmentTag;
if (semanticEquipmentTag != null) {
builder.withSemanticEquipmentTag(semanticEquipmentTag);
}
return builder; return builder;
} }
@ -212,6 +220,6 @@ public class ThingTypeXmlResult {
+ ", channelTypeReferences=" + channelTypeReferences + ", channelGroupTypeReferences=" + ", channelTypeReferences=" + channelTypeReferences + ", channelGroupTypeReferences="
+ channelGroupTypeReferences + ", extensibelChannelTypeIds=" + extensibleChannelTypeIds + channelGroupTypeReferences + ", extensibelChannelTypeIds=" + extensibleChannelTypeIds
+ ", properties=" + properties + ", configDescriptionURI=" + configDescriptionURI + ", 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}. * This is the test class for {@link ThingDTO}.
* *
* @author Christoph Weitkamp - Initial contribution * @author Christoph Weitkamp - Initial contribution
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class ThingDTOTest { 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, "channel1"), CoreItemFactory.STRING).build(),
ChannelBuilder.create(new ChannelUID(THING_UID, "channel2"), CoreItemFactory.STRING).build()) ChannelBuilder.create(new ChannelUID(THING_UID, "channel2"), CoreItemFactory.STRING).build())
.withConfiguration(new Configuration(Map.of("param1", "value1"))).withProperties(properties) .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); Thing result = ThingDTOMapper.map(ThingDTOMapper.map(subject), false);
assertThat(result, is(instanceOf(ThingImpl.class))); assertThat(result, is(instanceOf(ThingImpl.class)));
assertThat(result.getThingTypeUID(), is(THING_TYPE_UID)); assertThat(result.getThingTypeUID(), is(THING_TYPE_UID));
@ -67,6 +68,7 @@ public class ThingDTOTest {
assertThat(result.getProperties().values(), hasSize(1)); assertThat(result.getProperties().values(), hasSize(1));
assertThat(result.getProperties(), is(subject.getProperties())); assertThat(result.getProperties(), is(subject.getProperties()));
assertThat(result.getLocation(), is(subject.getLocation())); assertThat(result.getLocation(), is(subject.getLocation()));
assertThat(result.getSemanticEquipmentTag(), is(subject.getSemanticEquipmentTag()));
} }
@Test @Test

View File

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

View File

@ -12,6 +12,8 @@
<label>HUE Lamp</label> <label>HUE Lamp</label>
<description>My own great HUE Lamp.</description> <description>My own great HUE Lamp.</description>
<semantic-equipment-tag>LightBulb</semantic-equipment-tag>
<channel-groups> <channel-groups>
<channel-group id="alarm_system" typeId="alarm_system"/> <channel-group id="alarm_system" typeId="alarm_system"/>
</channel-groups> </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 Alex Tugarev - Adapted for constructor modification of ConfigDescriptionParameter
* @author Thomas Höfer - Thing type constructor modified because of thing properties introduction * @author Thomas Höfer - Thing type constructor modified because of thing properties introduction
* @author Wouter Born - Migrate tests from Groovy to Java * @author Wouter Born - Migrate tests from Groovy to Java
* @author Andrew Fiddian-Green - Added semanticEquipmentTag
*/ */
@NonNullByDefault @NonNullByDefault
public class ThingFactoryTest extends JavaOSGiTest { public class ThingFactoryTest extends JavaOSGiTest {
private static final String SEMANTIC_EQUIPMENT_TAG = "MotionDetector";
@Test @Test
public void createSimpleThing() { public void createSimpleThing() {
ThingType thingType = ThingTypeBuilder.instance("bindingId", "thingTypeId", "label").build(); ThingType thingType = ThingTypeBuilder.instance("bindingId", "thingTypeId", "label").build();
@ -349,4 +352,13 @@ public class ThingFactoryTest extends JavaOSGiTest {
}); });
registerService(channelGroupTypeProvider); 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));
}
} }