Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add documentation for Thing Model module and GenericThingProvider #4448

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions bundles/org.openhab.core.model.thing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# OpenHAB Core Thing Model

## Overview

The Thing Model module is a crucial component of OpenHAB's core architecture that handles the definition, parsing, and processing of Thing configurations. Things in OpenHAB represent physical devices or web services that can be integrated into the system.

## Key Components

### Formatting (`formatting/`)

- `ThingFormatter.xtend`: Handles the formatting of Thing definitions in the OpenHAB configuration syntax.

### Generator (`generator/`)

- `ThingGenerator.xtend`: Generates the necessary code for Thing implementations based on model definitions.

### Internal (`internal/`)

- `AbstractProviderLazyNullness.java`: Provides base implementation for lazy loading of Thing properties
- `GenericItemChannelLinkProvider.java`: Manages links between Items and Thing channels
- `GenericThingProvider.xtend`: Core provider implementation for Thing management

### Scoping (`scoping/`)

- `ThingScopeProvider.xtend`: Handles the scoping rules for Thing definitions

### Serializer (`serializer/`)

- `ThingSemanticSequencer.xtend`: Manages semantic sequencing of Thing definitions
- `ThingSyntacticSequencer.xtend`: Handles syntactic sequencing of Thing configurations
- `ThingSyntacticSequencerExtension.java`: Extension for Thing syntax processing

### Validation (`validation/`)

- `ThingValidator.xtend`: Validates Thing configurations to ensure correctness

### Value Converter (`valueconverter/`)

- `ThingValueConverters.java`: Handles conversion of Thing configuration values
- `UIDtoStringConverter.java`: Converts between UIDs and string representations

## Usage

### Thing Definition Example

Here's a simple example of how to define a Thing in your OpenHAB configuration:

```Thing mqtt:topic:livingroom "Living Room Sensor" @ "First Floor" [
broker="home-mqtt",
topic="home/livingroom/sensor",
refresh=60
]
```

This defines an MQTT sensor in the living room that reads data every 60 seconds.

## Key Features

The Thing Model helps you:

1. Define your smart devices in a readable way
2. Make sure your configurations are valid before they run
3. Handle different types of devices consistently
4. Keep your Things organized and manageable

Think of it as the blueprint system for your smart home devices - it helps OpenHAB understand what devices you have and how to talk to them.

## Working with Other Parts

The Thing Model doesn't work alone - it's part of a bigger system:

1. Talks directly to your physical devices through bindings
2. Works with Items to show device info in your UI
3. Helps with finding new devices on your network
4. Lets you change device settings while everything's running

## Development Tips

When working with Things, keep these points in mind:

### Keep It Clean

1. Use clear names for your Things
2. Group related Things together
3. Comment your configurations

### Play It Safe

1. Always validate your Thing configs before using them
2. Test your changes in a safe environment first
3. Back up working configurations

### Common Gotchas

1. Double-check your Thing IDs - they must be unique
2. Watch out for special characters in Thing names
3. Remember to handle offline devices gracefully

## Need more examples or have questions?

Check out:

1. The OpenHAB community forums
2. Example configurations in the addons repository
3. The binding developer guide
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,20 @@ import org.slf4j.Logger
import org.slf4j.LoggerFactory

/**
* {@link ThingProvider} implementation which computes *.things files.
* {@link ThingProvider} implementation which processes and manages Things defined in *.things files.
* This provider is responsible for:
*
* 1. Loading Things configurations from model files
* 2. Managing Thing lifecycle (creation, updates, deletion)
* 3. Handling dynamic updates when model files change
* 4. Coordinating with ThingHandlerFactories for Thing creation
* 5. Managing lazy loading and retry mechanisms for Thing initialization
*
* @author Oliver Libutzki - Initial contribution
* @author niehues - Fix ESH Bug 450236
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=450236 - Considering
* ThingType Description
* @author Simon Kaufmann - Added asynchronous retry in case the handler
* factory cannot load a thing yet (bug 470368),
* added delay until ThingTypes are fully loaded
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=450236 - Considering ThingType Description
* @author Simon Kaufmann - Added asynchronous retry in case the handler factory cannot load a thing yet
* (bug 470368), added delay until ThingTypes are fully loaded
* @author Markus Rathgeb - Add locale provider support
*/
@Component(immediate=true, service=ThingProvider)
Expand Down Expand Up @@ -113,6 +118,12 @@ class GenericThingProvider extends AbstractProviderLazyNullness<Thing> implement
thingsMap.values.flatten.toList
}

/**
* Creates Things from a given model file.
*
* @param modelName The name of the model file to process
* @throws IllegalStateException if model processing fails
*/
def private void createThingsFromModel(String modelName) {
logger.debug("Read things from model '{}'", modelName);
if (thingsMap.get(modelName) === null) {
Expand Down Expand Up @@ -203,6 +214,17 @@ class GenericThingProvider extends AbstractProviderLazyNullness<Thing> implement
return things + flattenModelThings(things.filter(typeof(ModelBridge)).map(b|b.things).flatten);
}

/**
* Creates a Thing instance with proper configuration and channels.
* This method:
* 1. Validates the Thing configuration
* 2. Sets up channels based on Thing type
* 3. Applies any model-specific overrides
*
* @param modelThing The Thing model to create from
* @param thingList Collection to add the created Thing to
* @param thingHandlerFactory Factory to create the Thing
*/
def private void createThing(ModelThing modelThing, Collection<Thing> thingList,
ThingHandlerFactory thingHandlerFactory) {
val ThingUID thingUID = getThingUID(modelThing, null)
Expand Down Expand Up @@ -357,6 +379,16 @@ class GenericThingProvider extends AbstractProviderLazyNullness<Thing> implement
return bridgeIds
}

/**
* Creates channels for a Thing based on its type and model configuration.
* Handles both manually defined channels and those from channel definitions.
*
* @param thingTypeUID UID of the Thing type
* @param thingUID UID of the Thing
* @param modelChannels Channels defined in the model
* @param channelDefinitions Channel definitions from the Thing type
* @return List of created channels
*/
def private List<Channel> createChannels(ThingTypeUID thingTypeUID, ThingUID thingUID,
List<ModelChannel> modelChannels, List<ChannelDefinition> channelDefinitions) {
val Set<String> addedChannelIds = newHashSet
Expand Down Expand Up @@ -633,6 +665,11 @@ class GenericThingProvider extends AbstractProviderLazyNullness<Thing> implement
]
}

/**
* Handles lazy initialization retry for Things that couldn't be created immediately.
* Implements a retry mechanism for Things that failed initial creation,
* typically due to missing dependencies or async loading issues.
*/
private val lazyRetryRunnable = new Runnable() {
override run() {
logger.debug("Starting lazy retry thread")
Expand Down Expand Up @@ -677,13 +714,23 @@ class GenericThingProvider extends AbstractProviderLazyNullness<Thing> implement
}
}

/**
* Stores information about Things that need to be initialized later.
* Used by the lazy retry mechanism when immediate Thing creation fails.
*/
@Data
private static final class QueueContent {
/** The Thing type identifier */
ThingTypeUID thingTypeUID
/** Human-readable label for the Thing */
String label
/** Thing configuration parameters */
Configuration configuration
/** Unique identifier for the Thing */
ThingUID thingUID
/** Bridge this Thing belongs to (if any) */
ThingUID bridgeUID
/** Factory responsible for creating this Thing */
ThingHandlerFactory thingHandlerFactory
}

Expand Down
Loading