Module: OpenHAB::Core::Items::Semantics

Included in:
GenericItem
Defined in:
lib/openhab/core/items/semantics.rb

Overview

Module for implementing semantics helper methods on Item in order to easily navigate the Semantic Model in your scripts. This can be extremely useful to find related items in rules that are executed for any member of a group.

Wraps org.openhab.core.model.script.actions.Semantics as well as adding a few additional convenience methods. Also includes classes for each semantic tag.

Be warned that the Semantic model is stricter than can actually be described by tags and groups on an Item. It makes assumptions that any given item only belongs to one semantic type (Location, Equipment, Point).

#Enumerable helper methods

Enumerable helper methods are also provided to complement the semantic model. These methods can be chained together to find specific item(s) based on custom tags or group memberships that are outside the semantic model.

The Enumerable helper methods apply to:

#Semantic Classes

Each Semantic Tag has a corresponding class within the org.openhab.core.semantics class hierarchy. These "semantic classes" are available as constants in the Semantics module with the corresponding name. The following table illustrates the semantic constants:

Semantic Constant openHAB's Semantic Class
Semantics::LivingRoom org.openhab.core.semantics.model.location.LivingRoom
Semantics::Lightbulb org.openhab.core.semantics.model.equipment.Lightbulb
Semantics::Control org.openhab.core.semantics.model.point.Control
Semantics::Switch org.openhab.core.semantics.model.point.Switch
Semantics::Power org.openhab.core.semantics.model.property.Power
... ...

These constants can be used as arguments to the #points, Enumerable#locations and Enumerable#equipments methods to filter their results. They can also be compared against the return value of #semantic_type, #location_type, #equipment_type, #point_type, and #property_type. They can even be used with DSL::Items::ItemBuilder#tag.

The semantic constants in the Semantics module are enhanced with TagClassMethods to provide easy access to the tags' additional attributes: label, synonyms, and description. For example, to get the synonyms for Semantics::Lightbulb in German: Semantics::Lightbulb.synonyms(java.util.Locale::GERMAN)

#Adding Custom Semantic Tags

openHAB 4 supports adding custom semantic tags to augment the standard set of tags to better suit your particular requirements.

For more information, see Semantics.add

Examples:

Working with tags

# Return an array of sibling points with a "Switch" tag
Light_Color.points(Semantics::Switch)

# check semantic type
LoungeRoom_Light.equipment_type == Semantics::Lightbulb
Light_Color.property_type == Semantics::Light

switches.items

Group   gFullOn
Group   gRoomOff

Group   eGarageLights        "Garage Lights"             (lGarage)                 [ "Lightbulb" ]
Dimmer  GarageLights_Dimmer  "Garage Lights"    <light>  (eGarageLights)           [ "Switch" ]
Number  GarageLights_Scene   "Scene"                     (eGarageLights, gFullOn, gRoomOff)

Group   eMudLights           "Mud Room Lights"           (lMud)                    [ "Lightbulb" ]
Dimmer  MudLights_Dimmer     "Garage Lights"    <light>  (eMudLights)              [ "Switch" ]
Number  MudLights_Scene      "Scene"                     (eMudLights, gFullOn, gRoomOff)

Find the switch item for a scene channel on a zwave dimmer

rule "turn dimmer to full on when switch double-tapped up" do
  changed gFullOn.members, to: 1.3
  run do |event|
    dimmer_item = event.item.points(Semantics::Switch).first
    dimmer_item.ensure << 100
  end
end

Turn off all the lights in a room

rule "turn off all lights in the room when switch double-tapped down" do
  changed gRoomOff.members, to: 2.3
  run do |event|
    event
      .item
      .location
      .equipments(Semantics::Lightbulb)
      .members
      .points(Semantics::Switch)
      .ensure.off
  end
end

Finding a related item that doesn't fit in the semantic model

# We can use custom tags to identify certain items that don't quite fit in the semantic model.
# The extensions to the Enumerable mentioned above can help in this scenario.

# In the following example, the TV `Equipment` has three `Points`. However, we are using custom tags
# `Application` and `Channel` to identify the corresponding points, since the semantic model
# doesn't have a specific property for them.

# Here, we use Enumerable#tagged
# to find the point with the custom tag that we want.

# Item model:
Group   gTVPower
Group   lLivingRoom                                 [ "LivingRoom" ]

Group   eTV             "TV"       (lLivingRoom)    [ "Television" ]
Switch  TV_Power        "Power"    (eTV, gTVPower)  [ "Switch", "Power" ]
String  TV_Application  "App"      (eTV)            [ "Control", "Application" ]
String  TV_Channel      "Channel"  (eTV)            [ "Control", "Channel" ]

# Rule:
rule 'Switch TV to Netflix on startup' do
  changed gTVPower.members, to: ON
  run do |event|
    application = event.item.points.tagged('Application').first
    application << 'netflix'
  end
end

Find all semantic entities regardless of hierarchy

# All locations
items.locations

# All rooms
items.locations(Semantics::Room)

# All equipments
items.equipments

# All lightbulbs
items.equipments(Semantics::Lightbulb)

# All blinds
items.equipments(Semantics::Blinds)

# Turn off all "Power control"
items.points(Semantics::Control, Semantics::Power).off

# All items tagged "SmartLightControl"
items.tagged("SmartLightControl")

See Also:

Defined Under Namespace

Modules: TagClassMethods

Constant Summary collapse

Tag =

This is a marker interface for all semantic tag classes.

org.openhab.core.semantics.Tag
Location =

This is the super interface for all types that represent a Location.

org.openhab.core.semantics.Location
Equipment =

This is the super interface for all types that represent an Equipment.

org.openhab.core.semantics.Equipment
Point =

This is the super interface for all types that represent a Point.

org.openhab.core.semantics.Point
Property =

This is the super interface for all property tags.

org.openhab.core.semantics.Property

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#equipmentItem? (readonly)

Gets the related Equipment Item of this Item.

Checks ancestor groups one level at a time, returning the first Equipment Item found.

Returns:



308
309
310
# File 'lib/openhab/core/items/semantics.rb', line 308

def equipment
  Actions::Semantics.get_equipment(self)&.then(&Proxy.method(:new))
end

#equipment_typeClass? (readonly)

Returns the sub-class of Equipment related to this Item.

In other words, the #semantic_type of this Item's Equipment.

Returns:

  • (Class, nil)


321
322
323
# File 'lib/openhab/core/items/semantics.rb', line 321

def equipment_type
  Actions::Semantics.get_equipment_type(self)&.ruby_class
end

#locationItem? (readonly)

Gets the related Location Item of this Item.

Checks ancestor groups one level at a time, returning the first Location Item found.

Returns:



282
283
284
# File 'lib/openhab/core/items/semantics.rb', line 282

def location
  Actions::Semantics.get_location(self)&.then(&Proxy.method(:new))
end

#location_typeClass? (readonly)

Returns the sub-class of Location related to this Item.

In other words, the #semantic_type of this Item's Location.

Returns:

  • (Class, nil)


295
296
297
# File 'lib/openhab/core/items/semantics.rb', line 295

def location_type
  Actions::Semantics.get_location_type(self)&.ruby_class
end

#point_typeClass? (readonly)

Returns the sub-class of Point this Item is tagged with.

Returns:

  • (Class, nil)


332
333
334
# File 'lib/openhab/core/items/semantics.rb', line 332

def point_type
  Actions::Semantics.get_point_type(self)&.ruby_class
end

#property_typeClass? (readonly)

Returns the sub-class of Property this Item is tagged with.

Returns:

  • (Class, nil)


343
344
345
# File 'lib/openhab/core/items/semantics.rb', line 343

def property_type
  Actions::Semantics.get_property_type(self)&.ruby_class
end

#semantic_typeClass? (readonly)

Returns the sub-class of Tag this Item is tagged with.

It will only return the first applicable Tag, preferring a sub-class of Location, Equipment, or Point first, and if none of those are found, looks for a Property.

Returns:

  • (Class, nil)


357
358
359
# File 'lib/openhab/core/items/semantics.rb', line 357

def semantic_type
  Actions::Semantics.get_semantic_type(self)&.ruby_class
end

Class Method Details

.self.add(**tags) ⇒ Array<Tag> .self.add(label: nil, synonyms: "", description: "", **tags) ⇒ Array<Tag>

Adds custom semantic tags.

Overloads:

  • .self.add(**tags) ⇒ Array<Tag>

    Quickly add one or more semantic tags using the default label, empty synonyms and descriptions.

    Examples:

    Add one semantic tag Balcony whose parent is Semantics::Outdoor (Location)

    Semantics.add(Balcony: Semantics::Outdoor)

    Add multiple semantic tags

    Semantics.add(Balcony: Semantics::Outdoor,
                  SecretRoom: Semantics::Room,
                  Motion: Semantics::Property)

    Parameters:

    • **tags (kwargs)

      Exactly one pair of tag => parent where tag is either a Symbol or a String for the tag to be added, and parent is either a Tag, a symbol or a string of an existing tag.

    Returns:

    • (Array<Tag>)

      An array of tags successfully added.

  • .self.add(label: nil, synonyms: "", description: "", **tags) ⇒ Array<Tag>

    Add a custom semantic tag with extra details.

    Examples:

    Semantics.add(SecretRoom: Semantics::Room, label: "My Secret Room",
      synonyms: "HidingPlace", description: "A room that requires a special trick to enter")

    Parameters:

    • label (String, nil) (defaults to: nil)

      Optional label. When nil, infer the label from the tag name, converting CamelCase to Camel Case

    • synonyms (String, Array<String,Symbol>) (defaults to: "")

      An array of synonyms, or a string containing a comma separated list of synonyms for this tag.

    • description (String) (defaults to: "")

      A longer description of the tag.

    • **tags (kwargs)

      Exactly one pair of tag => parent where tag is either a Symbol or a String for the tag to be added, and parent is either a Tag, a symbol or a string of an existing tag.

    Returns:

    • (Array<Tag>)

      An array of tags successfully added.

Returns:

  • (Array<Tag>)

    An array of tags successfully added.



436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
# File 'lib/openhab/core/items/semantics.rb', line 436

def self.add(label: nil, synonyms: "", description: "", **tags)
  raise "Tags must be specified" if tags.empty?
  if (tags.length > 1) && !(label.nil? && synonyms.empty? && description.empty?)
    raise "Additional options can only be specified when creating one tag"
  end

  synonyms = synonyms.map(&:to_s).map(&:strip).join(",") if synonyms.is_a?(Array)

  tags.map do |name, parent|
    parent_is_tag = parent.respond_to?(:java_class) && parent.java_class < Tag.java_class
    parent = parent_is_tag ? parent.java_class : parent.to_s
    name = name.to_s
    org.openhab.core.semantics.SemanticTags.add(name, parent, label, synonyms, description)
                                          &.then { const_missing(name) }
  end.compact
end

.lookup(id, locale = nil) ⇒ Tag?

Finds the semantic tag using its name, label, or synonyms.

Parameters:

  • id (String, Symbol)

    The tag name, label, or synonym to look up

  • locale (java.util.Locale) (defaults to: nil)

    The locale of the given label or synonym

Returns:

  • (Tag, nil)

    The semantic tag class if found, or nil if not found.



476
477
478
479
480
481
482
# File 'lib/openhab/core/items/semantics.rb', line 476

def self.lookup(id, locale = nil)
  id = id.to_sym
  return const_get(id) if constants.include?(id) || const_missing(id)

  locale = java.util.Locale.default if locale.nil?
  org.openhab.core.semantics.SemanticTags.get_by_label_or_synonym(id.to_s, locale).first&.ruby_class
end

.tagsArray<Tag>

Returns all available Semantic tags

Returns:

  • (Array<Tag>)

    an array containing all the Semantic tags



459
460
461
462
463
464
465
466
# File 'lib/openhab/core/items/semantics.rb', line 459

def self.tags
  java.util.stream.Stream.of(
    org.openhab.core.semantics.model.point.Points.stream,
    org.openhab.core.semantics.model.property.Properties.stream,
    org.openhab.core.semantics.model.equipment.Equipments.stream,
    org.openhab.core.semantics.model.location.Locations.stream
  ).flat_map(&:itself).map(&:ruby_class).iterator.to_a
end

Instance Method Details

#equipment?true, false

Checks if this Item is an Equipment

This is implemented as checking if the item's #semantic_type is an Equipment. I.e. an Item has a single #semantic_type.

Returns:

  • (true, false)


248
249
250
# File 'lib/openhab/core/items/semantics.rb', line 248

def equipment?
  Actions::Semantics.equipment?(self)
end

#location?true, false

Checks if this Item is a Location

This is implemented as checking if the item's #semantic_type is a Location. I.e. an Item has a single #semantic_type.

Returns:

  • (true, false)


236
237
238
# File 'lib/openhab/core/items/semantics.rb', line 236

def location?
  Actions::Semantics.location?(self)
end

#point?true, false

Checks if this Item is a Point

This is implemented as checking if the item's #semantic_type is a Point. I.e. an Item has a single #semantic_type.

Returns:

  • (true, false)


259
260
261
# File 'lib/openhab/core/items/semantics.rb', line 259

def point?
  Actions::Semantics.point?(self)
end

#points(*point_or_property_types) ⇒ Array<Item>

Return the related Point Items.

Searches this Equipment Item for Points that are tagged appropriately.

If called on a Point Item, it will automatically search for sibling Points (and remove itself if found).

Examples:

Get all points for a TV

eGreatTV.points

Search an Equipment item for its switch

eGuestFan.points(Semantics::Switch) # => [GuestFan_Dimmer]

Search a Thermostat item for its current temperature item

eFamilyThermostat.points(Semantics::Status, Semantics::Temperature)
# => [FamilyThermostat_AmbTemp]

Search a Thermostat item for is setpoints

eFamilyThermostat.points(Semantics::Control, Semantics::Temperature)
# => [FamilyThermostat_HeatingSetpoint, FamilyThermostat_CoolingSetpoint]

Given a A/V receiver's input item, search for its power item

FamilyReceiver_Input.points(Semantics::Switch) # => [FamilyReceiver_Switch]

Parameters:

  • point_or_property_types (Class)

    Pass 1 or 2 classes that are sub-classes of Point or Property. Note that when comparing against semantic tags, it does a sub-class check. So if you search for [Control], you'll get items tagged with [Switch].

Returns:



388
389
390
391
392
393
394
395
# File 'lib/openhab/core/items/semantics.rb', line 388

def points(*point_or_property_types)
  return members.points(*point_or_property_types) if equipment? || location?

  # automatically search the parent equipment (or location?!) for sibling points
  result = (equipment || location)&.points(*point_or_property_types) || []
  result.delete(self)
  result
end

#semantic?true, false

Checks if this Item has any semantic tags

Returns:

  • (true, false)


268
269
270
# File 'lib/openhab/core/items/semantics.rb', line 268

def semantic?
  !!semantic_type
end