32
32
import org .openhab .core .config .core .ConfigUtil ;
33
33
import org .openhab .core .config .core .Configuration ;
34
34
import org .openhab .core .i18n .LocaleProvider ;
35
- import org .openhab .core .model .yaml .YamlElementName ;
36
35
import org .openhab .core .model .yaml .YamlModelListener ;
37
- import org .openhab .core .model .yaml .YamlModelRepository ;
38
36
import org .openhab .core .service .ReadyMarker ;
39
37
import org .openhab .core .service .ReadyService ;
40
38
import org .openhab .core .service .StartLevelService ;
@@ -84,7 +82,6 @@ public class YamlThingProvider extends AbstractProvider<Thing>
84
82
85
83
private final Logger logger = LoggerFactory .getLogger (YamlThingProvider .class );
86
84
87
- private final YamlModelRepository modelRepository ;
88
85
private final BundleResolver bundleResolver ;
89
86
private final ThingTypeRegistry thingTypeRegistry ;
90
87
private final ChannelTypeRegistry channelTypeRegistry ;
@@ -104,32 +101,8 @@ public void run() {
104
101
logger .debug ("Starting lazy retry thread" );
105
102
while (!queue .isEmpty ()) {
106
103
for (QueueContent qc : queue ) {
107
- logger .trace ("Retry creating thing {}" , qc .thingUID );
108
- Thing newThing = qc .thingHandlerFactory .createThing (qc .thingTypeUID , qc .configuration , qc .thingUID ,
109
- qc .bridgeUID );
110
- if (newThing != null ) {
111
- logger .debug ("Successfully loaded thing \' {}\' during retry" , qc .thingUID );
112
- Thing oldThing = null ;
113
- for (Map .Entry <String , Collection <Thing >> entry : thingsMap .entrySet ()) {
114
- oldThing = entry .getValue ().stream ().filter (t -> t .getUID ().equals (newThing .getUID ()))
115
- .findFirst ().orElse (null );
116
- if (oldThing != null ) {
117
- mergeThing (newThing , oldThing );
118
- Collection <Thing > thingsForModel = Objects
119
- .requireNonNull (thingsMap .get (entry .getKey ()));
120
- thingsForModel .remove (oldThing );
121
- thingsForModel .add (newThing );
122
- logger .debug ("Refreshing thing \' {}\' after successful retry" , newThing .getUID ());
123
- if (!ThingHelper .equals (oldThing , newThing )) {
124
- notifyListenersAboutUpdatedElement (oldThing , newThing );
125
- }
126
- break ;
127
- }
128
- }
129
- if (oldThing == null ) {
130
- logger .debug ("Refreshing thing \' {}\' after retry failed because thing is not found" ,
131
- newThing .getUID ());
132
- }
104
+ if (retryCreateThing (qc .thingHandlerFactory , qc .thingTypeUID , qc .configuration , qc .thingUID ,
105
+ qc .bridgeUID )) {
133
106
queue .remove (qc );
134
107
}
135
108
}
@@ -153,12 +126,11 @@ private record QueueContent(ThingHandlerFactory thingHandlerFactory, ThingTypeUI
153
126
}
154
127
155
128
@ Activate
156
- public YamlThingProvider (final @ Reference YamlModelRepository modelRepository ,
157
- final @ Reference BundleResolver bundleResolver , final @ Reference ThingTypeRegistry thingTypeRegistry ,
129
+ public YamlThingProvider (final @ Reference BundleResolver bundleResolver ,
130
+ final @ Reference ThingTypeRegistry thingTypeRegistry ,
158
131
final @ Reference ChannelTypeRegistry channelTypeRegistry ,
159
132
final @ Reference ConfigDescriptionRegistry configDescriptionRegistry ,
160
133
final @ Reference LocaleProvider localeProvider ) {
161
- this .modelRepository = modelRepository ;
162
134
this .bundleResolver = bundleResolver ;
163
135
this .thingTypeRegistry = thingTypeRegistry ;
164
136
this .channelTypeRegistry = channelTypeRegistry ;
@@ -242,6 +214,7 @@ public void removedModel(String modelName, Collection<YamlThingDTO> elements) {
242
214
243
215
@ Reference (cardinality = ReferenceCardinality .MULTIPLE , policy = ReferencePolicy .DYNAMIC )
244
216
protected void addThingHandlerFactory (final ThingHandlerFactory thingHandlerFactory ) {
217
+ logger .debug ("addThingHandlerFactory {}" , thingHandlerFactory .getClass ().getSimpleName ());
245
218
thingHandlerFactories .add (thingHandlerFactory );
246
219
thingHandlerFactoryAdded (thingHandlerFactory );
247
220
}
@@ -278,16 +251,73 @@ public void onReadyMarkerRemoved(ReadyMarker readyMarker) {
278
251
loadedXmlThingTypes .remove (readyMarker .getIdentifier ());
279
252
}
280
253
281
- private void thingHandlerFactoryAdded (ThingHandlerFactory thingHandlerFactory ) {
282
- String bundleName = getBundleName (thingHandlerFactory );
283
- if (bundleName != null && loadedXmlThingTypes .contains (bundleName )) {
284
- logger .debug ("Refreshing models due to new thing handler factory {}" ,
285
- thingHandlerFactory .getClass ().getSimpleName ());
286
- thingsMap .keySet ().forEach (modelName -> {
287
- modelRepository .refreshModelElements (modelName ,
288
- getElementClass ().getAnnotation (YamlElementName .class ).value ());
289
- });
254
+ private void thingHandlerFactoryAdded (ThingHandlerFactory handlerFactory ) {
255
+ logger .debug ("thingHandlerFactoryAdded {} isThingHandlerFactoryReady={}" ,
256
+ handlerFactory .getClass ().getSimpleName (), isThingHandlerFactoryReady (handlerFactory ));
257
+ if (isThingHandlerFactoryReady (handlerFactory )) {
258
+ if (!thingsMap .isEmpty ()) {
259
+ logger .debug ("Refreshing models due to new thing handler factory {}" ,
260
+ handlerFactory .getClass ().getSimpleName ());
261
+ thingsMap .keySet ().forEach (modelName -> {
262
+ List <Thing > things = thingsMap .getOrDefault (modelName , List .of ()).stream ()
263
+ .filter (th -> handlerFactory .supportsThingType (th .getThingTypeUID ())).toList ();
264
+ if (!things .isEmpty ()) {
265
+ logger .info ("Refreshing YAML model {} ({} things with {})" , modelName , things .size (),
266
+ handlerFactory .getClass ().getSimpleName ());
267
+ things .forEach (thing -> {
268
+ if (!retryCreateThing (handlerFactory , thing .getThingTypeUID (), thing .getConfiguration (),
269
+ thing .getUID (), thing .getBridgeUID ())) {
270
+ // Possible cause: Asynchronous loading of the XML files
271
+ // Add the data to the queue in order to retry it later
272
+ logger .debug (
273
+ "ThingHandlerFactory \' {}\' claimed it can handle \' {}\' type but actually did not. Queued for later refresh." ,
274
+ handlerFactory .getClass ().getSimpleName (), thing .getThingTypeUID ());
275
+ queueRetryThingCreation (handlerFactory , thing .getThingTypeUID (),
276
+ thing .getConfiguration (), thing .getUID (), thing .getBridgeUID ());
277
+ }
278
+ });
279
+ } else {
280
+ logger .debug ("No refresh needed from YAML model {}" , modelName );
281
+ }
282
+ });
283
+ } else {
284
+ logger .debug ("No things yet loaded; no need to trigger a refresh due to new thing handler factory" );
285
+ }
286
+ }
287
+ }
288
+
289
+ private boolean retryCreateThing (ThingHandlerFactory handlerFactory , ThingTypeUID thingTypeUID ,
290
+ Configuration configuration , ThingUID thingUID , @ Nullable ThingUID bridgeUID ) {
291
+ logger .trace ("Retry creating thing {}" , thingUID );
292
+ Thing newThing = handlerFactory .createThing (thingTypeUID , configuration , thingUID , bridgeUID );
293
+ if (newThing != null ) {
294
+ logger .debug ("Successfully loaded thing \' {}\' during retry" , thingUID );
295
+ Thing oldThing = null ;
296
+ for (Collection <Thing > modelThings : thingsMap .values ()) {
297
+ oldThing = modelThings .stream ().filter (t -> t .getUID ().equals (newThing .getUID ())).findFirst ()
298
+ .orElse (null );
299
+ if (oldThing != null ) {
300
+ mergeThing (newThing , oldThing );
301
+ modelThings .remove (oldThing );
302
+ modelThings .add (newThing );
303
+ logger .debug ("Refreshing thing \' {}\' after successful retry" , newThing .getUID ());
304
+ if (!ThingHelper .equals (oldThing , newThing )) {
305
+ notifyListenersAboutUpdatedElement (oldThing , newThing );
306
+ }
307
+ break ;
308
+ }
309
+ }
310
+ if (oldThing == null ) {
311
+ logger .debug ("Refreshing thing \' {}\' after retry failed because thing is not found" ,
312
+ newThing .getUID ());
313
+ }
290
314
}
315
+ return newThing != null ;
316
+ }
317
+
318
+ private boolean isThingHandlerFactoryReady (ThingHandlerFactory thingHandlerFactory ) {
319
+ String bundleName = getBundleName (thingHandlerFactory );
320
+ return bundleName != null && loadedXmlThingTypes .contains (bundleName );
291
321
}
292
322
293
323
private @ Nullable String getBundleName (ThingHandlerFactory thingHandlerFactory ) {
@@ -300,20 +330,6 @@ private void thingHandlerFactoryAdded(ThingHandlerFactory thingHandlerFactory) {
300
330
String [] segments = thingUID .getAsString ().split (AbstractUID .SEPARATOR );
301
331
ThingTypeUID thingTypeUID = new ThingTypeUID (thingUID .getBindingId (), segments [1 ]);
302
332
303
- ThingHandlerFactory handlerFactory = thingHandlerFactories .stream ()
304
- .filter (thf -> thf .supportsThingType (thingTypeUID )).findFirst ().orElse (null );
305
- if (handlerFactory == null ) {
306
- if (modelLoaded ) {
307
- logger .info ("No ThingHandlerFactory found for thing {} (thing-type is {}). Deferring initialization." ,
308
- thingUID , thingTypeUID );
309
- }
310
- return null ;
311
- }
312
- String bundleName = getBundleName (handlerFactory );
313
- if (bundleName == null || !loadedXmlThingTypes .contains (bundleName )) {
314
- return null ;
315
- }
316
-
317
333
ThingType thingType = thingTypeRegistry .getThingType (thingTypeUID , localeProvider .getLocale ());
318
334
ThingUID bridgeUID = thingDto .bridge != null ? new ThingUID (thingDto .bridge ) : null ;
319
335
Configuration configuration = new Configuration (thingDto .config );
@@ -333,22 +349,22 @@ private void thingHandlerFactoryAdded(ThingHandlerFactory thingHandlerFactory) {
333
349
334
350
Thing thing = thingBuilder .build ();
335
351
336
- Thing thingFromHandler = handlerFactory . createThing ( thingTypeUID , configuration , thingUID , bridgeUID ) ;
337
- if ( thingFromHandler != null ) {
338
- mergeThing ( thingFromHandler , thing );
339
- logger . debug ( "Successfully loaded thing \' {} \' " , thingUID );
340
- } else {
341
- // Possible cause: Asynchronous loading of the XML files
342
- // Add the data to the queue in order to retry it later
343
- logger . debug (
344
- "ThingHandlerFactory \' {} \' claimed it can handle \' {}\' type but actually did not. Queued for later refresh." ,
345
- handlerFactory . getClass (). getSimpleName (), thingTypeUID );
346
- queue . add ( new QueueContent ( handlerFactory , thingTypeUID , configuration , thingUID , bridgeUID ));
347
- Thread thread = lazyRetryThread ;
348
- if ( thread == null || ! thread . isAlive ()) {
349
- thread = new Thread ( lazyRetryRunnable );
350
- lazyRetryThread = thread ;
351
- thread . start ( );
352
+ Thing thingFromHandler = null ;
353
+ ThingHandlerFactory handlerFactory = thingHandlerFactories . stream ()
354
+ . filter ( thf -> isThingHandlerFactoryReady ( thf ) && thf . supportsThingType ( thingTypeUID )). findFirst ()
355
+ . orElse ( null );
356
+ if ( handlerFactory != null ) {
357
+ thingFromHandler = handlerFactory . createThing ( thingTypeUID , configuration , thingUID , bridgeUID );
358
+ if ( thingFromHandler != null ) {
359
+ mergeThing ( thingFromHandler , thing );
360
+ logger . debug ( "Successfully loaded thing \' {}\' " , thingUID );
361
+ } else {
362
+ // Possible cause: Asynchronous loading of the XML files
363
+ // Add the data to the queue in order to retry it later
364
+ logger . debug (
365
+ "ThingHandlerFactory \' {} \' claimed it can handle \' {} \' type but actually did not. Queued for later refresh." ,
366
+ handlerFactory . getClass (). getSimpleName (), thingTypeUID ) ;
367
+ queueRetryThingCreation ( handlerFactory , thingTypeUID , configuration , thingUID , bridgeUID );
352
368
}
353
369
}
354
370
@@ -383,7 +399,7 @@ private List<Channel> createChannels(ThingTypeUID thingTypeUID, ThingUID thingUI
383
399
configDescriptionRegistry .getConfigDescription (descUriO ));
384
400
}
385
401
} else {
386
- logger .warn ("Channel type {} could not be found." , channelTypeUID );
402
+ logger .warn ("Channel type {} could not be found for thing '{}' ." , channelTypeUID , thingUID );
387
403
}
388
404
}
389
405
@@ -439,4 +455,15 @@ private void mergeThing(Thing target, Thing source) {
439
455
// add the channels only defined in source list to the target list
440
456
ThingHelper .addChannelsToThing (target , channelsToAdd );
441
457
}
458
+
459
+ private void queueRetryThingCreation (ThingHandlerFactory handlerFactory , ThingTypeUID thingTypeUID ,
460
+ Configuration configuration , ThingUID thingUID , @ Nullable ThingUID bridgeUID ) {
461
+ queue .add (new QueueContent (handlerFactory , thingTypeUID , configuration , thingUID , bridgeUID ));
462
+ Thread thread = lazyRetryThread ;
463
+ if (thread == null || !thread .isAlive ()) {
464
+ thread = new Thread (lazyRetryRunnable );
465
+ lazyRetryThread = thread ;
466
+ thread .start ();
467
+ }
468
+ }
442
469
}
0 commit comments