HABot Walkthrough (2/n): Semantic Tagging & Item Resolving

Tags: #<Tag:0x00007fe057ff20f0>

(Yannick Schaus) #1

This is a wiki topic, regular members as well as staff may edit it freely and are encouraged to do so! The content will eventually be migrated somewhere in the main documentation when it’s stabilized and enough feedback has been received. When replying to posts on this series, please try to stay on-topic - there will be several of them, each covering a particular feature or area, so please look for the appropriate topic and reply there, or create a new topic. Thanks! :slight_smile:

When using HABot, one of the main challenges is to figure out the right information from the original natural language query. Items are openHAB’s conceptual model of your home so this is where the information will be found. To do that, the interpreter and associated skills have to transform Entities extracted by Natural Language Processing into actual items to display or act on.

There has been several iterations on how to perform this task, but ultimately it led to the introduction of the semantics core bundle in the Eclipse SmartHome framework.

By applying semantic tags to your items, you will able to describe more accurately what they actually represent (an equipment, a location) as well as relations between them; it will then become possible for clients like HABot to perform advanced queries on them, like “items related to a certain property (Temperature) located in a certain place (Ground Floor)”; additionally, attributes to refer to them will be provided for you in several languages so clients won’t have to rely on the items’ labels alone. It is also an attempt at unifying how to describe and match items among different natural language “assistant” integrations like Alexa, Google etc. and avoid custom implementations of this particular problem in each of them. Please note that semantics are a very recent addition to ESH, so they are still subject to change and will be expanded over time!

The Eclipse SmartHome Ontology & Semantic Tags

The ESH ontology was built according to continuing discussions about a tag library, and the Brick Schema as a baseline. The schema below illustrates its initial version:

The ontology defines 4 main types: Location, Property, Point and Equipment, with associated tags for each of them. As you can see on the schema, the entire model is an actual Java class hierarchy (the 4 main types are also derived from the generic Tag interface). Therefore GarageDoor is a kind of Door, OpenState is a kind of Status, and Basement is a kind of Floor, which is also a location inherited from Indoor.

According to the schema, currently you can only tag an item with one of the Location, Equipment or Point tags, but you can combine a Point tag and a Property tag on the same item.

The following is also applicable and noteworthy:

  • The hasLocation relations and the isPartOf relation for locations will be using group memberships to determine objects in a location, so it only makes sense to put Location tags on Group items which represent a location, like a floor or a room
Group gFF           "First Floor"   <firstfloor>        ["FirstFloor"]
Group gGF           "Ground Floor"  <groundfloor>       ["GroundFloor"]
Group gC            "Cellar"        <cellar>            ["Basement"]
Group Garden        "Garden"        <garden>            ["Garden"]
Group GF_Living     "Living Room"   <video>     (gGF)   ["LivingRoom"]
Group GF_Kitchen    "Kitchen"       <kitchen>   (gGF)   ["Kitchen"]
  • Points and Properties should usually used together, so that the “relatesTo” relation is implied by having a single item tagged with a Point & Property. If a Property tag is found without the associated Point, the item will implicitely be considered to be a Status if the item is read only, or a Control if it can accept commands.
Number Temperature_GF_Corridor "Corridor [%.1f °C]"    ["Temperature", "Measurement"]
Switch Light_FF_Bath_Ceiling   "Ceiling"               ["Light"]
Dimmer Temperature_Setpoint    "Temperature [%.1f °C]" ["Setpoint", "Temperature"]
  • In theory (!) Equipment tags are only valid on groups, similary to locations, so that the group memberships build the hasPoint and isPointOf relations; that being said, nothing currently prevents a non-Group item from representing an Equipment without specifying which kind of Point it measures or controls - this is useful when there is only one item for that equipment for the unspecified main functionality (or Point) of that equipment:
# Equipment with multiple Points
Group   gKitchenSensor (gKitchen)                        ["MotionDetector"]
Contact KitchenSensor_MotionDetected   (gKitchenSensor)  ["Status"]
Switch  KitchenSensor_LowBattery       (gKitchenSensor)  ["LowBattery"]
Switch  KitchenSensor_Tampered         (gKitchenSensor)  ["Tampered"]

# Equipments with no explicit Points
Rollershutter Shutter_GF_Living        "Livingroom"    (GF_Living)      ["Blinds"]
Contact       Garage_Door              "Garage Door [MAP(en.map):%s]"   ["GarageDoor"]
Contact       Window_GF_Kitchen        "Kitchen [MAP(en.map):%s]"       ["Window"]
Switch        Heating_GF_Corridor      "Corridor"      (GF_Corridor)    ["HVAC"]

(in the future it will likely be possible to specify a Point and Property along with an Equipment).

Tag-provided Terms and User-defined Synonyms

As mentioned above, tagged items will automatically be provided with default labels, plurals and synonyms predefined in ESH in several languages useable in queries. These Terms may also be expanded on a per-item basis, when:

  • there is no tag in the ontology exactly matching the item’s nature;
  • the item needs to be referred to with a specific name in queries (in addition to the label), like “Amy’s Room”.

For these scenarios, a comma-separated list of user-supplied synonyms can be provided for individual items using metadata in the synonyms namespace. Just tag the item with the closest matching tag you can find in the ontology and add one or several synonyms, separating them with commas - note that the item’s label will also implicitely added as a term for the item, therefore no need to add it as a synonym!

Group GF_Toilet     "Toilet"        (gGF)   ["Bathroom"] { synonyms="Toilets,WC,Restroom" }
Group FF_Office     "Office"        (gFF)   ["Room"]     { synonyms="Study" }
Group FF_Son        "Oliver's Room" (gFF)   ["Bedroom"]  { synonyms="Oli's Room" }
Group FF_Daughter   "Amelia's Room" (gFF)   ["Bedroom"]  { synonyms="Amy's Room" }
Group FF_Bed        "Bedroom"       (gFF)   ["Bedroom"]  { synonyms="Master Bedroom,Parents' Room" }

If you define item synonyms, plurals have to be supplied too (when it makes sense) so you can refer to a group of them using the plural forms.

In short, when looking for items related to a particular term, the framework will look in:

  1. The item tags’ label and synonyms (in the current language);
  2. The item’s label, without the format information between brackets;
  3. The user-supplied synonyms in the synonyms namespace.

How HABot Resolves Items

One of the components of the natural language processing in HABot’s case apart from intent classification is the entity extraction, that is, extracting the important parts of the sentence and determining their type.
A lot of training focuses on sentences containing “<what> in the <where>”, which will be extracted in entities with the object (“what”) and location (“where”) types.

Note that “object” is not in ESH’s ontology; for technical and historical reasons, HABot is unable to distinguish between equipments, points and properties, therefore an object in HABot’s terminology can refer indifferently to a Equipment, Point or Property as defined in ESH’s ontology.

Terms associated with individual items apart from its label are called “(named) attributes” in HABot’s terminology for the same reasons; in other words, attributes are what HABot considers how each item can be referred to. When chatting, the interpreter will resolve items from the entities extracted from the sentence (object=Lights, location=Kitchen) by looking at items and their attributes.

You can review which attributes are associated with your items in HABot’s UI: click on Settings in the sidebar, then the View item attributes option:

The chips in the last column indicate whether the attribute is an object or a location (with icons), and whether it comes from a tag (in blue) or a synonym defined with metadata (in black). Remember, the label is also automatically considered.

Next Steps

The next article will introduce a cool feature of the HABot Progressive Web App - how you can have it app-like full screen experience on your Android phone or desktop computer instead of running it in the browser.

HABot Walkthrough (1/n): Introduction and Installation
Official Google Assistant Integration for openHAB
Next generation design: A Paper UI replacement proposal
Semantics and Metadata for Alexa Skill
(Rich Koshak) #2

Let’s say I’m already using Tags for Google Assistant or Hue Emulation or some such. Do these tags get added to that list or is this a separate set of square brackets?

The same question for the synonyms, if I’ve some Items bound to 1.x version bindings, do I add the synonyms as another binding config or is this a separate set of curly brackets?

Assuming they are separate elements where do they go in this order?

itemtype itemname "labeltext [stateformat]" <iconname> (group1, group2, ...) ["tag1", "tag2", ...] {bindingconfig}

I think the tutorial could benefit from a quick walk through showing how one would configure a simple Item, like a living room lamp. Let’s say I have a LivingRoom_Lamp Item and no relevant Groups defined yet. Walk the user through:

  1. First, let’s put the Item into a room. Create a Group called FF_LivingRoom with the label “Living Room”. The FF in the name is telling us this room is on the first floor.
  2. Now we need to add the symaptic tag to the Group to tell HABot what room this this Group represents. So add ["LivingRoom"] as a tag.
  3. But wait, we also want to tell HABot that this room is on the First floor so let’s create a gFF Item with the label “First Floor” and the tag [“FirstFloor”]. Now add the gFF Group to the FF_LivingRoom Group.

and so on.

About all I know at this point is what I’ve read so I’m not actually certain I’ve got the reasoning above correct, hence my comment.

It seems pretty important to get everything correct for this.

It would be nice to have a version of the ontology that we can copy and paste from to make sure we get the spelling correct. I’m not sure the best way to represent that (Tables?).

If I have a smoke alarm that has a battery, should I use a Battery tag for the alarm’s Battery Level Item or Status or Measurement or something else? Having worked with ontologies before I know these ambiguities can be maddening. Some advice will certainly help users new to this sort of thing.

Great write ups! I look forward to using HABot. I think it is a fantastic approach!

(Mark) #3

Here’s how I did the Setpoints for my Ecobee thermostats.

Number Ecobee_1_DesiredCool    "Ecobee Desired Cool [%.1f °F]"  (gFF)  ["Setpoint", "Temperature"]     { ecobee="<[xxx#runtime.desiredCool]", synonyms="Cooling Setpoint" }
Number Ecobee_1_DesiredHeat    "Ecobee Desired Heat [%.1f °F]"  (gFF)  ["Setpoint", "Temperature"]     { ecobee="<[xxx#runtime.desiredHeat]", synonyms="Heating Setpoint" }
Number Ecobee_2_DesiredCool    "Ecobee Desired Cool [%.1f °F]"  (gSF)  ["Setpoint", "Temperature"]     { ecobee="<[yyy#runtime.desiredCool]", synonyms="Cooling Setpoint" }
Number Ecobee_2_DesiredHeat    "Ecobee Desired Heat [%.1f °F]"  (gSF)  ["Setpoint", "Temperature"]     { ecobee="<[yyy#runtime.desiredHeat]", synonyms="Heating Setpoint" }

(Rich Koshak) #4

OK, so this implies there are not separate elements for this. We are using standard tags and standard binding configs.


(Yannick Schaus) #5


The semantic tags are regular tags and how to specify item metadata is described here (this is imported from http://www.eclipse.org/smarthome/documentation/concepts/items.html#item-metadata): https://www.openhab.org/docs/concepts/items.html#item-metadata

Good idea! Maybe it would be good to reiterate the advice in the previous article (1/x) to try out the demo package on a fresh instance first, so that the .items files can be analyzed to understand how it all works. If you have improvements to make to the article after you’ve tried it, remember it’s a wiki :wink:

It would be nice to have a version of the ontology that we can copy and paste from to make sure we get the spelling correct. I’m not sure the best way to represent that (Tables?).

Indeed, but since It’s likely to change (@mhilbush has already proposed suggestions today), instead of maintaining it here maybe the best would be to emphasize the real source which is https://github.com/eclipse/smarthome/blob/master/bundles/core/org.eclipse.smarthome.core.semantics/model/SemanticTags.csv (2nd column)

Unfortunately it’s difficult for me to answer… those are among the big questions with this current iteration of the ontology - to be honest, at this point here’s hoping the collected complaints and reports about its shortcomings will help shape it into something that’s useable.

Thanks for the feedback!

(Michael Cumming) #6

Really exciting stuff. Agree with the comments above, its important that we get the ontology right.

In my setup, this is how I have arranged my locations - however, I have used the verbiage “Area”. Interested in any thoughts.

I am planning on a post on how I utilize occupancy in my setup, but ask if you want any details.



Hierarchial representation of the home in gHome

Area is a physicial discrete location that contains items that are in that area.

The "Area" tag allows scripts to navigate through areas using the concept of parent/child
relationships. This allows operations on areas and pass those operations to any child area.

Occupancy is a concept where each area has an occupied or vacant state. It utilizes items
in an area to control occupancy. Full details are in occupancy.py.

Metadata: (used by occupancy.py)
    Occupancy = "Settings" 
        Value Time = XXX  XXX = minutes that the area is occupied after an occupancy event from an item in that area

            OccupancyActions = actions to take when an area becomes occupied
                LightsOn = turn on all lights in a area tagged with "Lighting"
                SceneOn = turn on scene in a area using any scene tagged with "AreaScene"
                SceneOnIfDark = as above, but only when dark out
                LightsOnIfDark = as above, but only when dark out

            VacantActions = actions to take when an area becomes vacant
                LightsOff = turn off all lights in a area tagged with "Lighting"
                SceneOff = turn off scene in an area using any scene tagged with "AreaScene"
                AVOff = turn off an AV device tagged with "AVPower"
                ExhaustFansOff = turn of any items tagged with "ExhaustFan"


Group    gHome                                              "Home"                          <house>                 (gRoot)                           ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "" ]}  // hierarchical list of areas           

    Group    gHM_Exterior                                   "Exterior"                      <lawnmower>             (gHome)                           ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "AVOff" ]} 
        Group    gEX_Patio                                  "Patio"                         <terrace>               (gHM_Exterior)                    ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff,AVOff" ]}
        Group    gEX_BackYard                               "Backyard"                      <lawnmower>             (gHM_Exterior)                    ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "" ]}
        Group    gEX_FrontYard                              "Front Yard"                    <lawnmower>             (gHM_Exterior)                    ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "" ]}
        Group    gEX_FrontPorch                             "Front Porch"                   <none>                  (gHM_Exterior)                    ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "" ]}
        Group    gEX_BackPorch                              "Back Porch"                    <none>                  (gHM_Exterior)                    ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff" ]}
        Group    gEX_Garage                                 "Garage"                        <none>                  (gHM_Exterior)                    ["Area"]        {Occupancy = "Settings" [ Time = 10, OccupiedActions = "SceneOnIfDark", VacantActions = "SceneOff" ]}

    Group   gHM_Interior                                    "Inside"                        <house>                 (gHome)                           ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "" ]}  
        Group   gIN_Basement                                "Basement"                      <cellar>                (gHM_Interior)                    ["Area"]        {Occupancy = "Settings" [ Time = 60, VacantActions = "SceneOff,AVOff" ]} 
            Group    gBM_RecRoom                            "Rec Room"                      <none>                  (gIN_Basement)                    ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff" ]}
            Group    gBM_Bathroom                           "Bathroom"                      <bath>                  (gIN_Basement)                    ["Area"]        {Occupancy = "Settings" [ Time = 15, VacantActions = "SceneOff,ExhaustFansOff" ]}
            Group    gBM_StorageRoom                        "Storage Room"                  <suitcase>              (gIN_Basement)                    ["Area"]        {Occupancy = "Settings" [ Time = 5, VacantActions = "LightsOff", OccupiedActions = "LightsOn" ]}
            Group    gBM_Stairs                             "Stairs Up"                     <qualityofservice>      (gIN_Basement)                    ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "" ]}
        Group   gIN_MainFloor                               "First Floor"                   <groundfloor>           (gHM_Interior)                    ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "" ]}
            Group    gMF_LivingRoom                         "Living Room"                   <sofa>                  (gIN_MainFloor)                   ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff,AVOff" ]}
            Group    gMF_DiningRoom                         "Dining"                                                (gIN_MainFloor)                   ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff" ]}
            Group    gMF_FrontEntryHallway                  "Front Entry"                   <none>                  (gIN_MainFloor)                   ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff" ]}
            Group    gMF_Kitchen                            "Kitchen"                       <kitchen>               (gIN_MainFloor)                   ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff,AVOff" ]}
            Group    gMF_BackHallway                        "Back Hallway"                  <none>                  (gIN_MainFloor)                   ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff" ]}
            Group    gMF_Pantry                             "Pantry"                        <none>                  (gIN_MainFloor)                   ["Area"]        {Occupancy = "Settings" [ Time = 20, VacantActions = "LightsOff" ]}
            Group    gMF_Mudroom                            "Mudroom"                       <none>                  (gIN_MainFloor)                   ["Area"]        {Occupancy = "Settings" [ Time = 15, VacantActions = "SceneOff" ]}    
                Group    gMF_MudroomCloset                  "Mudroom Closet"                <none>                  (gMF_Mudroom)                     ["Area"]        {Occupancy = "Settings" [ Time = 5, VacantActions = "LightsOff" ]}    
            Group    gMF_EatingArea                         "Eating Area"                   <none>                  (gIN_MainFloor)                   ["Area"]        {Occupancy = "Settings" [ Time = 60, VacantActions = "LightsOff" ]}
            Group    gMF_FamilyRoom                         "Family Room"                   <parents_2_4>           (gIN_MainFloor)                   ["Area"]        {Occupancy = "Settings" [ Time = 60, VacantActions = "SceneOff,AVOff" ]}
            Group    gMF_Bathroom                           "Bathroom"                      <bath>                  (gIN_MainFloor)                   ["Area"]        {Occupancy = "Settings" [ Time = 15, VacantActions = "SceneOff,ExhaustFansOff" ]}
            Group    gMF_Stairs                             "Stairs"                        <none>                  (gIN_MainFloor)                   ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff" ]}
        Group   gIN_SecondFloor                             "Second Floor"                  <firstfloor>            (gHM_Interior)                    ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff" ]}
            Group    gSF_Master                             "Master"                        <bedroom_red>           (gIN_SecondFloor)                 ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff" ]}
                Group    gSF_MasterBedroom                  "Master Bedroom"                <bedroom_red>           (gSF_Master)                      ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff,AVOff" ]}
                Group    gSF_MasterSittingRoom              "Master Sitting Room"           <none>                  (gSF_Master)                      ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff,AVOff" ]}
                Group    gSF_MasterBathroom                 "Master Bathroom"               <bath>                  (gSF_Master)                      ["Area"]        {Occupancy = "Settings" [ Time = 30, VacantActions = "SceneOff,AVOff" ]}
                    Group    gSF_MasterBathroomShower       "Master Bathroom Shower"        <bath>                  (gSF_MasterBathroom)              ["Area"]        {Occupancy = "Settings" [ Time = 15, VacantActions = "SceneOff,ExhaustFansOff" ]}
                    Group    gSF_MasterBathroomToilet       "Master Bathroom Toilet"        <bath>                  (gSF_MasterBathroom)              ["Area"]        {Occupancy = "Settings" [ Time = 10, VacantActions = "SceneOff,ExhaustFansOff" ]}
                    Group    gSF_MasterBathroomVanity       "Master Bathroom Vanity"        <bath>                  (gSF_MasterBathroom)              ["Area"]        {Occupancy = "Settings" [ Time = 30, VacantActions = "SceneOff,ExhaustFansOff" ]}
                Group    gSF_MasterNorthCloset              "Master North Closet"           <none>                  (gSF_Master)                      ["Area"]        {Occupancy = "Settings" [ Time = 10, VacantActions = "LightsOff" ]}
                Group    gSF_MasterSouthCloset              "Master South Closet"           <none>                  (gSF_Master)                      ["Area"]        {Occupancy = "Settings" [ Time = 10, VacantActions = "LightsOff" ]}
            Group    gSF_Hallway                            "Hallway"                       <corridor>              (gIN_SecondFloor)                 ["Area"]        {Occupancy = "Settings" [ Time = 30, VacantActions = "SceneOff" ]}
            Group    gSF_Stairs                             "Stairs Up"                     <qualityofservice>      (gIN_SecondFloor)                 ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff" ]}
            Group    gSF_GuestBedroom                       "Guest Room"                    <parents_4_3>           (gIN_SecondFloor)                 ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "LightsOff" ]}
            Group    gSF_KidsBathroom                       "Kids Bathroom"                 <bath>                  (gIN_SecondFloor)                 ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff,ExhaustFansOff" ]}
            Group    gSF_KidsNorthBedroom                   "Kids North Bedroom"            <none>                  (gIN_SecondFloor)                 ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "LightsOff" ]}
                Group    gSF_KidsNorthBedroomCloset         "Kids North Closet"             <none>                  (gIN_SecondFloor)                 ["Area"]        {Occupancy = "Settings" [ Time = 15, VacantActions = "LightsOff" ]}
                Group    gSF_KidsNorthVanity                "Kids North Vanity"             <none>                  (gIN_SecondFloor)                 ["Area"]        {Occupancy = "Settings" [ Time = 15, VacantActions = "LightsOff" ]}
            Group    gSF_KidsSouthBedroom                   "Kids South Bedroom"            <none>                  (gIN_SecondFloor)                 ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "LightsOff" ]}
                Group    gSF_KidsSouthBedroomCloset         "Kids South Closet"             <none>                  (gIN_SecondFloor)                 ["Area"]        {Occupancy = "Settings" [ Time = 15, VacantActions = "LightsOff" ]}
                Group    gSF_KidsSouthVanity                "Kids South Vanity"             <none>                  (gIN_SecondFloor)                 ["Area"]        {Occupancy = "Settings" [ Time = 15, VacantActions = "LightsOff" ]}
            Group    gSF_LaundryRoom                        "Laundry Room"                  <none>                  (gIN_SecondFloor)                 ["Area"]        {Occupancy = "Settings" [ Time = 10, VacantActions = "SceneOff" ]}             
        Group   gIN_ThirdFloor                              "Third Floor"                   <attic>                 (gHM_Interior)                    ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "SceneOff" ]}            
            Group    gTF_Bedroom                            "Bedroom"                       <bedroom>               (gIN_ThirdFloor)                  ["Area"]        {Occupancy = "Settings" [ Time = 120, VacantActions = "LightsOff" ]}
            Group    gTF_Office                             "Office"                        <office>                (gIN_ThirdFloor)                  ["Area"]        {Occupancy = "Settings" [ Time = 60, VacantActions = "SceneOff" ]}                                

(Yannick Schaus) #7

@mjcumming interesting stuff!

You might want to know that as part as the new “official” ESH semantics support, there’s a “semantic metadata provider” which will describe the semantics (type and relations) in metadata - you can look up this metadata with /rest/items?metadata=semantics. The goal is also to expose those semantics to scripts like yours.

This means, the semantic tags in this example:

Group gGF           "Ground Floor"  <groundfloor>       ["GroundFloor"]
Group GF_Living     "Living Room"   <video>     (gGF)   ["LivingRoom"]
Number Temperature_GF_Corridor "Corridor [%.1f °C]" (GF_Living)    ["Temperature", "Measurement"]

will translate in the API call as:

    "members": [],
    "link": "http://localhost:8080/rest/items/gGF",
    "state": "NULL",
    "metadata": {
      "semantics": {
        "value": "Location_Indoor_Floor_GroundFloor"
    "editable": false,
    "type": "Group",
    "name": "gGF",
    "label": "Ground Floor",
    "category": "groundfloor",
    "tags": [
    "groupNames": []
    "members": [],
    "link": "http://localhost:8080/rest/items/GF_Living",
    "state": "NULL",
    "metadata": {
      "semantics": {
        "value": "Location_Indoor_Room_LivingRoom",
        "config": {
          "isPartOf": "gGF"
    "editable": false,
    "type": "Group",
    "name": "GF_Living",
    "label": "Living Room",
    "category": "video",
    "tags": [
    "groupNames": [
    "link": "http://localhost:8080/rest/items/Temperature_GF_Living",
    "state": "19.2",
    "stateDescription": {
      "pattern": "%.1f °C",
      "readOnly": false,
      "options": []
    "metadata": {
      "semantics": {
        "value": "Point_Measurement",
        "config": {
          "relatesTo": "Property_Temperature",
          "hasLocation": "GF_Living"
    "editable": false,
    "type": "Number",
    "name": "Temperature_GF_Living",
    "label": "Living Room",
    "category": "temperature",
    "tags": [
    "groupNames": [

Note how the complete types and relations to other items (isPartOf, hasLocation) and types (relatedTo) are clearly reported in the “semantics” metadata namespace. This might help you when traversing hierarchies like you are doing.

(Michael Cumming) #8

I have read through the ESH semantics and think this is a great start to allow easier setups and automation using generic rules and concepts.

My understanding from the link above (correct me if I am wrong) is that the location semantics is to categorize locations types but does not allow for a hierarchical representation of the physical layout of a building - correct or am I missing something?

I also think some of the verbiage used will cause confusion depending on locale. ie. in the US/Canada I am not familiar with anyone calling the basement a cellar or the main floor the group floor. etc. Or perhaps that is more regional as well and I just haven’t experienced it.

(Yannick Schaus) #9

The “isPartOf” relation between different Location items is supposed to be exactly that.
In the example above, you’ll see for GF_Living:

      "semantics": {
        "value": "Location_Indoor_Room_LivingRoom",
        "config": {
          "isPartOf": "gGF"

which means that GF_Living is part of gFF which is a Floor. The relation was built because GF_Living in a member of the gFF group.

Thanks to you I just realized both the example and the demo.items file in the demo package is wrong :smile:
The item is indeed called “Cellar” in the demo package but the valid tag from the ontology should indeed be “Basement” and Cellar is only one of the synonyms (line https://github.com/eclipse/smarthome/blob/master/bundles/core/org.eclipse.smarthome.core.semantics/model/SemanticTags.csv line 9). I’ll change the post above but will have a do a PR to correct that :roll_eyes:

(Michael Cumming) #10

I see the isPartOf portion. Is there is method to determine child locations?

One concern I have with the semantics model so far is that they seem to be addressing 2 different concepts without identifying it …

  1. Locations/Area/Room type ie a bathroom, bedroom etc

  2. Actual physical location within a home.

Additionally, the semantics need to be altered by locale or some other differentiator that will allow changing based on where people live as we all use different verbiage to describe similar things (ie bathroom). I am not using synonyms is adequate for this…

I added a comment on GitHub as well

(Angelos) #11

Absolutely great stuff
I just started updating all my *.items files with several tags and they work fine (in parallel with the Skill related tags)


Switch P10_Light "P10 Light" <switch> (gGroups..) ["Light", "Lighting"] { channel="UID" }

(Vincent Regaud) #12

Yes please

(Dave Gurr) #13

What’s best practise in working with Presence items?

Ideally I’d like to be able to ask HABot “Is David Home?”, or “Who’s home?” and get a suitable card displayed.

(Curlyel) #14

First of all: This is amazing new stuff!
Have to admit: I’m really excited about it!
Thanks Yannick for bringing this new level to openHAB!

I’ve just started tagging my items these days like others here :wink:
Usually, I’m trying to put as many as possible into groups to avoid multiple replications of the same definitions.

Deploying goups for assigning “points” and “properties” to items seems not working.

This works (notice the synonyms at the end of the line):

Number TI03_Illu  "Illuminance [%.0f Lm]"    (gBuero) ["Light"] channel="zigbee:xx:yy:illuminance",synonyms="Helligkeit,Beleuchtung,Lichtintensität"}

But I’d rather like to have the synonyms defined just once for all sensors, e.g. (not working!):

Group   gIlluminance    "Helligkeit"   <status>    ["Light"]   {synonyms="Helligkeit,Beleuchtung,Lichtintensität"}
Number   TI03_Illu    "Illuminance [%.0f Lm]"    (gBuero, gIlluminance) {channel="zigbee:xx:yy:illuminance"}

to avoid repititions of the same code.

Is there a way of doing this already?

(Yannick Schaus) #15

No, sorry, previous iterations allowed these automatic group inheritance scenarios but since the introduction of the semantics in ESH, it’s more controlled and not possible anymore - so you have to specify the synonyms for all items.
But if a query matches group items, normally they should be expanded…

(Curlyel) #16

Thanks a lot Yannick - and: Happy new year! :wink:

Your answer let me start thinking about the group inheritance for points and properties and their synonyms:

Was’nt sure, if I got you right here, so I’ve just gave it a try.
And indeed, the following IS WORKING:
(notice “Light” is directly tagged to the item AND is tagged to inherited group gIlluminance too)

Group   gIlluminance    "Helligkeit"   <status>    ["Light"]   {synonyms="Helligkeit,Beleuchtung,Lichtintensität"}
Number   TI03_Illu    "Illuminance [%.0f Lm]"    (gBuero, gIlluminance) ["Light"] {channel="zigbee:xx:yy:illuminance"}

Yes, I can still use the synonyms for “Light” to query the illuminance item :slight_smile:

Sure, this brings some redundant configuration since the property “Light” is assigned to the item directly AND is inherited through the group gIlluminance. I’ve understood, that the property “Light” has to be assigned on the actual item directly.

But: In contrast to my former try, this configuration brings me the expansion of the synonyms for “Light” through the group inheritance.

Means: My list of synonyms has just to be maintained in one place instead on multiple items.
This is great!

Thanks for bringing me to think about this!

(Yannick Schaus) #17

Happy new year too! Glad you got it working!

However I even think the tags are not necessary, i.e. I just tried what you previously said is not working, and it does in fact work for me:

Group   gIlluminance    "Helligkeit"   <status>    ["Light"]   {synonyms="Helligkeit,Beleuchtung,Lichtintensität"}
Number   TI03_Illu    "Illuminance [%.0f Lm]"    (gIlluminance)
Number   TI04_Illu    "Illuminance [%.0f Lm]"    (gIlluminance)



So I don’t know why it wasn’t working before.
A disclaimer: Note that the fact that a group is expanded when referred to like this a feature specific to HABot, not a feature of ESH semantics. Other clients relying on the semantics might not implement this behavior, so it’s safer to at least tag all items with the proper semantic tag like intended.

(Curlyel) #18

Thanks for your investigations…

Mmh. Just checked, it’s working here too now without the explicit tagging on the item level :wink:
So I’m happy with HABot for that :wink:

To sum up:

  1. For HABot I can leverage the group inheritance for assigning all the four semantic tag-types (location/points/properties/equipment) as well as for my own synonyms.
  2. For possible other semantic-based bundles, I have to add individual tags on the items.
  3. If I do both above, I stay at least “compatible” with HABot and others while probably (certainly?) not having the synonyms available for the “non-HABot” semantic clients as long as I do not replicate the synonyms to each and every affected item.

Right so far?

(Yannick Schaus) #19

Yes, you’re exactly right.

(Curlyel) #20

Still investigating how to get my tagging right :wink:

Just tried to get some of my Sonos items tagged:

Group   gBuero	     		"Büro" 			                <office> 	    (gOG)           ["Room"]         {synonyms="Arbeitszimmer,Büro,Gästezimmer"}

Group	gSonosBuero											<receiver>      (gSonos)                            ["Receiver"]
Player 	SonosBuero			"Sonos"					        <receiver>      (gBuero,gSonosBuero,gSonosPlayer) 	["Control"]	{  channel="sonos:PLAY5:Buero:control" }
String  SonosBuero_State    "Status [%s]"                   <receiver>      (gBuero,gSonosBuero,gSonosState)    ["Status"]  {  channel="sonos:PLAY5:Buero:state" }
Dimmer	SonosBuero_Vol		"Lautstärke [%.0f %%]"			<soundvolume>   (gBuero,gSonosBuero,gSonosVol)	    ["Control"]	{  channel="sonos:PLAY5:Buero:volume" }
Dimmer	SonosBuero_NVol		"Durchsagelautst. [%.0f %%]" 	                (gBuero,gSonosBuero,gSonosNVol)
String	SonosBuero_Radio	"Radio [%.16s]"					                (gBuero,gSonosBuero,gSonosRadio)	 	        {  channel="sonos:PLAY5:Buero:radio" }
String	SonosBuero_Track	"Track [%.16s]"					                (gBuero,gSonosBuero)	            ["Status"] 	{  channel="sonos:PLAY5:Buero:currenttrack" }

First of all I noticed, that the widget/card is rendered differently when queried through the location group or individually. In the first case, just the state (play/pause etc.) is shown but no control widget is rendered. In the latter case, the expected widget is shown:

It’s not that important for now, but though I’m curious to know where this came from?

Second thing I’ve discovered:
HABot seems not to like values less than 10 :smile: :smile: :smile:

Any idea what’s the reason for this?

When I enter single digit number as two-digit (“8” -> “08”), then the value is accepted: